您的位置:首页 > 编程语言 > Java开发

Spring 基于事件的通信

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

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

Java代码


public class MyEvent extends ApplicationEvent {

/** */

private static final long serialVersionUID = 1L;

/**

* @param source

*/

public MyEvent(Object source) {

super(source);

}

}

Java代码


@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代码


@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代码


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代码


<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代码


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代码


/**

* 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代码


/**

* 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代码


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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: