ApplicationListener
监听器通过监听容器中发布的一些事件,只要事件发生,来触发监听器的回调,来完成事件驱动开发。
基于java.util.EventListener接口,实现Observer design pattern观察者设计模式
当向容器中注册时,将相应地过滤事件,仅调用侦听器以匹配事件对象。
public interface ApplicationListener<E extends ApplicationEvent>
监听 ApplicationEvent 及其下面的子事件;
步骤:
1. 写一个监听器(ApplicationListener实现类)来监听某个事件(ApplicationEvent及其子类)
2. 把监听器加入到容器;
3. 只要容器中有相关事件的发布,我们就能监听到这个事件;
ContextRefreshedEvent:容器刷新完成(所有bean都完全创建)会发布这个事件;
ContextClosedEvent:关闭容器会发布这个事件;
4. 发布一个事件:
applicationContext.publishEvent();
//发布事件; applicationContext.publishEvent(new ApplicationEvent(new String("我发布的事件")) { });
原理
现在有三个事件
ContextRefreshedEvent、IOCTest_Ext$1[source=我发布的事件]、ContextClosedEvent;
1. ContextRefreshedEvent事件:
1.1 容器创建对象:refresh();
1.2 finishRefresh();容器刷新完成会发布ContextRefreshedEvent事件
// Last step: publish corresponding event. finishRefresh();
2. 自己发布事件;
3. 容器关闭会发布ContextClosedEvent;
事件发布流程
publishEvent(new ContextRefreshedEvent(this));
1. 获取事件的多播器(派发器):getApplicationEventMulticaster()
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
2. multicastEvent派发事件:
3. 获取到所有的ApplicationListener;
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); } }
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
3.1 如果有Executor,可以支持使用Executor进行异步派发;
Executor executor = getTaskExecutor();
3.2 否则,同步的方式直接执行listener方法;invokeListener(listener, event);
拿到listener回调onApplicationEvent方法;
流程图
事件多播器(派发器)是如何创建的?
1. 容器创建对象:refresh();
2. initApplicationEventMulticaster();初始化ApplicationEventMulticaster;
// Initialize event multicaster for this context. initApplicationEventMulticaster();
2.1 先去容器中找有没有id=“applicationEventMulticaster”的组件;
2.2如果没有,那就创建一个
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
并且加入到容器中
我们就可以在其他组件要派发事件,自动注入这个applicationEventMulticaster;
我们可以提前注入一个applicationEventMulticaster并指定多个executor
向容器中注册listener
// Check for listener beans and register them. registerListeners();
从容器中拿到所有的监听器,把他们注册到applicationEventMulticaster中;
for (String listenerBeanName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); }
创建listener的方式
@EventListener与SmartInitializingSingleton
除了之前的实现ApplicationListener之外,
还可以通过使用@EventListener注解的方式
原理
@EventListener
原理:使用EventListenerMethodProcessor处理器来解析方法上的@EventListener;
Register {@link EventListener} annotated method as individual {@link ApplicationListener}
instances.
这个处理器的作用就是把@EventListener注解的方法注册为一个ApplicationListener的instance
EventListenerMethodProcessor的类图
其获取@EventListener注解的方法
org.springframework.context.event.EventListenerMethodProcessor#processBean
try { annotatedMethods = MethodIntrospector.selectMethods(targetType, new MethodIntrospector.MetadataLookup<EventListener>() { @Override public EventListener inspect(Method method) { return AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class); } }); }
SmartInitializingSingleton 原理:->afterSingletonsInstantiated();
1. ioc容器创建对象并refresh();
2. finishBeanFactoryInitialization(beanFactory);初始化剩下的单实例bean(在spring aop中有看到)
2.1 先创建所有的单实例bean;getBean();
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
// Trigger post-initialization callback for all applicable beans... for (String beanName : beanNames) { Object singletonInstance = getSingleton(beanName); if (singletonInstance instanceof SmartInitializingSingleton) { final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance; if (System.getSecurityManager() != null) { AccessController.doPrivileged(new PrivilegedAction<Object>() { @Override public Object run() { smartSingleton.afterSingletonsInstantiated(); return null; } }, getAccessControlContext()); } else { smartSingleton.afterSingletonsInstantiated(); } } }
触发所有适用bean的后初始化回调...
2.2 获取所有创建好的单实例bean,判断是否是SmartInitializingSingleton类型的;
如果是就调用afterSingletonsInstantiated();
流程图:
之后refresh方法继续向下,就执行finishRefresh方法
之后就回到上面的ApplicationListener这块,通过事件多播器发布事件