Spring 源码解析 ---- 事件监听
2016-11-23 10:08
375 查看
一. 测试用例
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);
}
}
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() 方法
广播器我们又经常成为事件
我们关注的是 SimpleApplicationEventMulticaster 事件类的具体实现,继续 debug 进去,看到此类继承自 AbstractApplicationEventMulticaster, 而 AbstractApplicationEventMulticaster 中有许多 add**Listener、delete**Listener 之类的方法,可以知道这是典型的观察者模式的应用。
继续看如下方法:事件在这里广播,遍历所有监听器,通知监听器
这个方法 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);
}
}
}
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);
}
}
}
相关文章推荐
- 【spring源码学习】spring的事件发布监听机制源码解析
- spring boot实战(第三篇)事件监听源码分析
- Spring5源码解析-Spring框架中的事件和监听器
- (转)spring boot实战(第三篇)事件监听源码分析
- Spring 源码 事件监听
- Spring源码解析-事件
- Spring----AOP面向切面编程例子解析(附源码)
- Spring 注入的事件监听模式
- Spring源码之旅(3)_BeanDefinition的解析与注册
- Android 小項目之---- 計算器 使用同一個事件监听完成 加减乘除 (附源码)
- Spring源码解析:Bean的实例化与依赖注入(四)
- Spring源码解析-BeanDefinition在IOC容器中的注册(三)
- Spring之事件监听
- Spring之事件监听
- Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法
- Spring源码分析-配置文件的解析(二)
- Spring源码学习-容器初始化之FileSystemXmlApplicationContext(二)路径格式及解析方式(上) 推荐
- spring 事件监听
- 郭克华手机编程教学视频----我的练习源码(18)Canvas事件监听:
- 深入剖析Spring Web源码(十八) - 视图解析和视图显示 - 更多的视图解析器