一. 测试用例
package main.java.com.wenniuwuren.spring.event.listener;
import org.springframework.context.ApplicationEvent;
/**
* 定义监听事件
* Created by hzzhuyibin on 2016/11/22.
*/
public class TestEvent extends ApplicationEvent {
public String msg;
/**
* Create a new ApplicationEvent.
*
* @param source the object on which the event initially occurred (never {@code null})
*/
public TestEvent(Object source) {
super(source);
}
public TestEvent(Object source, String msg) {
super(source);
this.msg = msg;
}
public void print() {
System.out.println(msg);
}
}
package main.java.com.wenniuwuren.spring.event.listener;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
/**
* 定义监听器
* Created by hzzhuyibin on 2016/11/22.
*/
public class TestListener implements ApplicationListener{
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof TestEvent) {
TestEvent testEvent = (TestEvent)event;
testEvent.print();
}
}
}
listenerTest.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name="testListener" class="main.java.com.wenniuwuren.spring.event.listener.TestListener"/>
</beans>
测试类:
package main.java.com.wenniuwuren.spring.event.listener;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
*
* Created by Yibin_Zhu on 2016/11/21.
*/
public class Test{
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("main/resources/listenerTest.xml");
// 不仅仅可以指定 beanName,也可以有构造函数或者工厂方法的方法参数
TestEvent testEvent = new TestEvent("hello", "wenniuwuren");
context.publishEvent(testEvent);
}
}
二. 源码解析
debug 到 AbstractApplicationContext 类的 initApplicationEventMulticaster() 方法
广播器我们又经常成为事件
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 + "]");
}
}
}
我们关注的是 SimpleApplicationEventMulticaster 事件类的具体实现,继续 debug 进去,看到此类继承自 AbstractApplicationEventMulticaster, 而 AbstractApplicationEventMulticaster 中有许多 add**Listener、delete**Listener 之类的方法,可以知道这是典型的
观察者模式的应用。
继续看如下方法:事件在这里广播,遍历所有监听器,通知监听器
@Override
public void multicastEvent(ApplicationEvent event) {
multicastEvent(event, resolveDefaultEventType(event));
}
@Override
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
@Override
public void run() {
invokeListener(listener, event);
}
});
}
else {
invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
listener.onApplicationEvent(event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
listener.onApplicationEvent(event);
}
}
这个方法 debug 结束,回到 AbstractApplicationContext 类,debug 进 registerListeners() 方法:注册监听器
protected void registerListeners() {
// 硬编码的方式注册监听器
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// 配置文件注册监听器
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}