Spring 基于事件的通信
2016-02-03 09:08
525 查看
Spring 应用上下文支持基于事件的Bean间通信。在基于事件的通信模式中,事件的发送者不需要关系,事件的监听者。这样可以使消息的发送者和监听者进行解耦。
在Spring中所有事件类必须继承自ApplicationEvent,这样任何bean都可以调用事件发布者的publishEvent()方法,发布一个事件。
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
public class MyEvent extends ApplicationEvent {
/** */
private static final long serialVersionUID = 1L;
/**
* @param source
*/
public MyEvent(Object source) {
super(source);
}
}
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
@Component("eventPublisher")
public class EventPublisher implements ApplicationEventPublisherAware {
private ApplicationEventPublisher applicationEventPublisher;
public void ckeckout(){
applicationEventPublisher.publishEvent(new MyEvent(this));
}
/**
* @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher)
*/
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher=applicationEventPublisher;
}
}
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
@Component
public class MyListener implements ApplicationListener<MyEvent> {
/**
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println(Thread.currentThread().getName()+";"+event.getTimestamp());
}
}
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
public class Test {
/**
*
* @param args
* @author zhangwei<wei.zw@corp.netease.com>
*/
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
EventPublisher cashier = (EventPublisher) context.getBean("eventPublisher");
for(int i=0;i<20;i++) {
cashier.ckeckout();
}
}
}
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="keepAliveSeconds" value="30000" />
<property name="maxPoolSize" value="1000" />
<property name="queueCapacity" value="200" />
</bean>
<bean id="applicationEventMulticaster"
class="org.springframework.context.event.SimpleApplicationEventMulticaster">
<property name="taskExecutor" ref="taskExecutor" />
</bean>
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
taskExecutor-1;1454033201241
taskExecutor-2;1454033201242
taskExecutor-3;1454033201242
taskExecutor-4;1454033201242
taskExecutor-5;1454033201243
taskExecutor-1;1454033201243
taskExecutor-3;1454033201243
taskExecutor-3;1454033201243
taskExecutor-2;1454033201243
taskExecutor-5;1454033201243
taskExecutor-1;1454033201243
taskExecutor-4;1454033201243
taskExecutor-3;1454033201243
taskExecutor-2;1454033201244
taskExecutor-5;1454033201244
taskExecutor-5;1454033201244
taskExecutor-4;1454033201244
taskExecutor-3;1454033201244
taskExecutor-2;1454033201244
taskExecutor-5;1454033201244
通过上面的一个示例,实现了异步的基于事件通信。
在AbstractApplicationContext中发布事件的实现如下,首先获取applicationEventMulticaster,通过其发布事件。
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
/**
* Publish the given event to all listeners.
* <p>Note: Listeners get initialized after the MessageSource, to be able
* to access it within listener implementations. Thus, MessageSource
* implementations cannot publish events.
* @param event the event to publish (may be application-specific or a
* standard framework event)
*/
public void publishEvent(ApplicationEvent event) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
getApplicationEventMulticaster().multicastEvent(event);
if (this.parent != null) {
this.parent.publishEvent(event);
}
}
在看看ApplicaitonEventMulticaster的初始化逻辑,如果在有配置过applicationEventMulticaster则直接使用,否则创建一个;注意,配置是ID必须是applicationEventMulticaster
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
/**
* Initialize the ApplicationEventMulticaster.
* Uses SimpleApplicationEventMulticaster if none defined in the context.
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
再看看ApplicationEventMulticaster中又是如何发布事件的。如果有配置线程池,则异步处理,否则同步处理。
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
public void multicastEvent(final ApplicationEvent event) {
for (final ApplicationListener listener : getApplicationListeners(event)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@SuppressWarnings("unchecked")
public void run() {
listener.onApplicationEvent(event);
}
});
}
else {
listener.onApplicationEvent(event);
}
}
}
转自:http://wujiu.iteye.com/blog/2274871
在Spring中所有事件类必须继承自ApplicationEvent,这样任何bean都可以调用事件发布者的publishEvent()方法,发布一个事件。
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
public class MyEvent extends ApplicationEvent {
/** */
private static final long serialVersionUID = 1L;
/**
* @param source
*/
public MyEvent(Object source) {
super(source);
}
}
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
@Component("eventPublisher")
public class EventPublisher implements ApplicationEventPublisherAware {
private ApplicationEventPublisher applicationEventPublisher;
public void ckeckout(){
applicationEventPublisher.publishEvent(new MyEvent(this));
}
/**
* @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher)
*/
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher=applicationEventPublisher;
}
}
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
@Component
public class MyListener implements ApplicationListener<MyEvent> {
/**
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println(Thread.currentThread().getName()+";"+event.getTimestamp());
}
}
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
public class Test {
/**
*
* @param args
* @author zhangwei<wei.zw@corp.netease.com>
*/
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
EventPublisher cashier = (EventPublisher) context.getBean("eventPublisher");
for(int i=0;i<20;i++) {
cashier.ckeckout();
}
}
}
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="keepAliveSeconds" value="30000" />
<property name="maxPoolSize" value="1000" />
<property name="queueCapacity" value="200" />
</bean>
<bean id="applicationEventMulticaster"
class="org.springframework.context.event.SimpleApplicationEventMulticaster">
<property name="taskExecutor" ref="taskExecutor" />
</bean>
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
taskExecutor-1;1454033201241
taskExecutor-2;1454033201242
taskExecutor-3;1454033201242
taskExecutor-4;1454033201242
taskExecutor-5;1454033201243
taskExecutor-1;1454033201243
taskExecutor-3;1454033201243
taskExecutor-3;1454033201243
taskExecutor-2;1454033201243
taskExecutor-5;1454033201243
taskExecutor-1;1454033201243
taskExecutor-4;1454033201243
taskExecutor-3;1454033201243
taskExecutor-2;1454033201244
taskExecutor-5;1454033201244
taskExecutor-5;1454033201244
taskExecutor-4;1454033201244
taskExecutor-3;1454033201244
taskExecutor-2;1454033201244
taskExecutor-5;1454033201244
通过上面的一个示例,实现了异步的基于事件通信。
在AbstractApplicationContext中发布事件的实现如下,首先获取applicationEventMulticaster,通过其发布事件。
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
/**
* Publish the given event to all listeners.
* <p>Note: Listeners get initialized after the MessageSource, to be able
* to access it within listener implementations. Thus, MessageSource
* implementations cannot publish events.
* @param event the event to publish (may be application-specific or a
* standard framework event)
*/
public void publishEvent(ApplicationEvent event) {
Assert.notNull(event, "Event must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Publishing event in " + getDisplayName() + ": " + event);
}
getApplicationEventMulticaster().multicastEvent(event);
if (this.parent != null) {
this.parent.publishEvent(event);
}
}
在看看ApplicaitonEventMulticaster的初始化逻辑,如果在有配置过applicationEventMulticaster则直接使用,否则创建一个;注意,配置是ID必须是applicationEventMulticaster
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
/**
* Initialize the ApplicationEventMulticaster.
* Uses SimpleApplicationEventMulticaster if none defined in the context.
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
再看看ApplicationEventMulticaster中又是如何发布事件的。如果有配置线程池,则异步处理,否则同步处理。
Java代码
![](http://wujiu.iteye.com/images/icon_star.png)
public void multicastEvent(final ApplicationEvent event) {
for (final ApplicationListener listener : getApplicationListeners(event)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@SuppressWarnings("unchecked")
public void run() {
listener.onApplicationEvent(event);
}
});
}
else {
listener.onApplicationEvent(event);
}
}
}
转自:http://wujiu.iteye.com/blog/2274871
相关文章推荐
- Java中的时间、时区和夏令时
- spring整合junit集成测试
- Java的一些坑
- Java结构型设计模式中的适配器模式与桥接模式解析
- 搭建一个struts2+spring+hibernate框架
- ubuntu下部署eclipse集成hadoop\android\web\GCC开发环境小记
- Java手动创建一个内存泄漏的程序
- 怎样改动Myeclipse10.7的Servlet模板
- spring ioc,aop工作原理
- JAVA常用函数总结分享。
- Java 中带参带返回值方法的使用
- Java 中带参无返回值方法的使用
- Java 中无参无返回值方法的使用
- JAVA中的包装类
- java面向对象的基础扫描
- JAVA中的匿名内部类
- Java中this关键字的几种用法
- 深入理解Java内存模型(七)——总结
- 深入理解Java内存模型(六)——final
- cmd运行Java程序的问题