一. 测试用例
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); } } }