Spring 基于事件的通信

21 篇文章 0 订阅

Spring 应用上下文支持基于事件的Bean间通信。在基于事件的通信模式中,事件的发送者不需要关系,事件的监听者。这样可以使消息的发送者和监听者进行解耦。

在Spring中所有事件类必须继承自ApplicationEvent,这样任何bean都可以调用事件发布者的publishEvent()方法,发布一个事件。

 

 

 

Java代码   收藏代码
  1. public class MyEvent extends ApplicationEvent {  
  2.   
  3.     /**  */  
  4.     private static final long serialVersionUID = 1L;  
  5.   
  6.   
  7.     /** 
  8.      * @param source 
  9.      */  
  10.     public MyEvent(Object source) {  
  11.         super(source);  
  12.           
  13.     }  
  14.   
  15. }  

 

Java代码   收藏代码
  1. @Component("eventPublisher")  
  2. public class EventPublisher implements ApplicationEventPublisherAware {  
  3.       
  4.     private ApplicationEventPublisher applicationEventPublisher;  
  5.       
  6.       
  7.     public void ckeckout(){  
  8.         applicationEventPublisher.publishEvent(new MyEvent(this));  
  9.     }  
  10.   
  11.     /**  
  12.      * @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher) 
  13.      */  
  14.     @Override  
  15.     public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {  
  16.         this.applicationEventPublisher=applicationEventPublisher;  
  17.     }  
  18.   
  19. }  

 

Java代码   收藏代码
  1. @Component  
  2. public class MyListener implements ApplicationListener<MyEvent> {  
  3.   
  4.     /**  
  5.      * @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent) 
  6.      */  
  7.     @Override  
  8.     public void onApplicationEvent(MyEvent event) {  
  9.         System.out.println(Thread.currentThread().getName()+";"+event.getTimestamp());  
  10.     }  
  11.   
  12. }  

 

Java代码   收藏代码
  1. public class Test {  
  2.   
  3.     /** 
  4.      *  
  5.      * @param args 
  6.      * @author zhangwei<wei.zw@corp.netease.com> 
  7.      */  
  8.     public static void main(String[] args) {  
  9.         ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");  
  10.         EventPublisher cashier = (EventPublisher) context.getBean("eventPublisher");  
  11.         for(int i=0;i<20;i++) {  
  12.             cashier.ckeckout();  
  13.         }  
  14.     }  
  15.   
  16. }  

 

Java代码   收藏代码
  1. <bean id="taskExecutor"  
  2.     class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">  
  3.     <property name="corePoolSize" value="5" />  
  4.     <property name="keepAliveSeconds" value="30000" />  
  5.     <property name="maxPoolSize" value="1000" />  
  6.     <property name="queueCapacity" value="200" />  
  7. </bean>  
  8. <bean id="applicationEventMulticaster"  
  9.     class="org.springframework.context.event.SimpleApplicationEventMulticaster">  
  10.     <property name="taskExecutor" ref="taskExecutor" />  
  11. </bean>  

 

Java代码   收藏代码
  1. taskExecutor-1;1454033201241  
  2. taskExecutor-2;1454033201242  
  3. taskExecutor-3;1454033201242  
  4. taskExecutor-4;1454033201242  
  5. taskExecutor-5;1454033201243  
  6. taskExecutor-1;1454033201243  
  7. taskExecutor-3;1454033201243  
  8. taskExecutor-3;1454033201243  
  9. taskExecutor-2;1454033201243  
  10. taskExecutor-5;1454033201243  
  11. taskExecutor-1;1454033201243  
  12. taskExecutor-4;1454033201243  
  13. taskExecutor-3;1454033201243  
  14. taskExecutor-2;1454033201244  
  15. taskExecutor-5;1454033201244  
  16. taskExecutor-5;1454033201244  
  17. taskExecutor-4;1454033201244  
  18. taskExecutor-3;1454033201244  
  19. taskExecutor-2;1454033201244  
  20. taskExecutor-5;1454033201244  

 

 

 

通过上面的一个示例,实现了异步的基于事件通信。

 

在AbstractApplicationContext中发布事件的实现如下,首先获取applicationEventMulticaster,通过其发布事件。

 

 

Java代码   收藏代码
  1. /** 
  2.      * Publish the given event to all listeners. 
  3.      * <p>Note: Listeners get initialized after the MessageSource, to be able 
  4.      * to access it within listener implementations. Thus, MessageSource 
  5.      * implementations cannot publish events. 
  6.      * @param event the event to publish (may be application-specific or a 
  7.      * standard framework event) 
  8.      */  
  9.     public void publishEvent(ApplicationEvent event) {  
  10.         Assert.notNull(event, "Event must not be null");  
  11.         if (logger.isTraceEnabled()) {  
  12.             logger.trace("Publishing event in " + getDisplayName() + ": " + event);  
  13.         }  
  14.         getApplicationEventMulticaster().multicastEvent(event);  
  15.         if (this.parent != null) {  
  16.             this.parent.publishEvent(event);  
  17.         }  
  18.     }  

     在看看ApplicaitonEventMulticaster的初始化逻辑,如果在有配置过applicationEventMulticaster则直接使用,否则创建一个;注意,配置是ID必须是applicationEventMulticaster

Java代码   收藏代码
  1. /** 
  2.      * Initialize the ApplicationEventMulticaster. 
  3.      * Uses SimpleApplicationEventMulticaster if none defined in the context. 
  4.      * @see org.springframework.context.event.SimpleApplicationEventMulticaster 
  5.      */  
  6.     protected void initApplicationEventMulticaster() {  
  7.         ConfigurableListableBeanFactory beanFactory = getBeanFactory();  
  8.         if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {  
  9.             this.applicationEventMulticaster =  
  10.                     beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);  
  11.             if (logger.isDebugEnabled()) {  
  12.                 logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");  
  13.             }  
  14.         }  
  15.         else {  
  16.             this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);  
  17.             beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);  
  18.             if (logger.isDebugEnabled()) {  
  19.                 logger.debug("Unable to locate ApplicationEventMulticaster with name '" +  
  20.                         APPLICATION_EVENT_MULTICASTER_BEAN_NAME +  
  21.                         "': using default [" + this.applicationEventMulticaster + "]");  
  22.             }  
  23.         }  
  24.     }  

 再看看ApplicationEventMulticaster中又是如何发布事件的。如果有配置线程池,则异步处理,否则同步处理。

 

Java代码   收藏代码
  1. public void multicastEvent(final ApplicationEvent event) {  
  2.         for (final ApplicationListener listener : getApplicationListeners(event)) {  
  3.             Executor executor = getTaskExecutor();  
  4.             if (executor != null) {  
  5.                 executor.execute(new Runnable() {  
  6.                     @SuppressWarnings("unchecked")  
  7.                     public void run() {  
  8.                         listener.onApplicationEvent(event);  
  9.                     }  
  10.                 });  
  11.             }  
  12.             else {  
  13.                 listener.onApplicationEvent(event);  
  14.             }  
  15.         }  
  16.     }  

 



转自:http://wujiu.iteye.com/blog/2274871

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值