目录
一、概述
ApplicationListener接口用来监听容器发布的事件,用来事件驱动模型开发。
在方法上使用@EventListener注解,作用与实现ApplicationListener接口一致,都可用来监听事件。
二、运行流程
2.1 容器在refresh方法的prepareBeanFactory方法中添加了类型为ApplicationListenerDetector的后置处理器。
2.1.1 ApplicationListenerDetector后置处理器主要是用来搜索发现实现了ApplicationListener接口的bean(包括innerBean也会被搜索到),将其添加到容器的监听器集合中。
因为innerBean不能通过容器的getBeanNamesForType方法得到,所以在refresh方法的registerListeners方法中无法将innerBean监听器添加到多播器中。
innerBean 参考什么是Spring inner beans?_Leon_Jinhai_Sun的博客-优快云博客
2.1.2 在组件创建初始化完成后,调用postProcessAfterInitialization方法,将实现了ApplicationListener接口的组件对象(包括innerBean对象)通过容器的addApplicationListener方法添加到监听器集合中。
2.2 在refresh方法中调用initApplicationEventMulticaster方法,初始化applicationEventMulticaster应用事件多播器(派发器)。事件多播器主要是在容器发布事件时,通过遍历applicationEventMulticaster事件多播器的监听器集合,将事件发布到各个监听器中。
2.2.1 initApplicationEventMulticaster方法中先判断容器是否有组件id为applicationEventMulticaster的事件多播器对象。若是有,则从容器中获取组件对象,并赋值给容器的applicationEventMulticaster属性。
若是没有,则容器会默认创建类型为SimpleApplicationEventMulticaster的对象,并赋值给容器的applicationEventMulticaster属性和添加到容器的单实例集合中。
我们可以自定义创建事件多播器对象,并加入到容器的单实例集合中。
2.3 通过refresh方法的registerListeners方法注册监听器 。
2.3.1 registerListeners方法中,先遍历容器之前存储的applicationListeners监听器集合,调用事件多播器的addApplicationListener方法,将监听器对象添加到事件多播器的defaultRetriever.applicationListeners中。
2.3.2 遍历容器中实现了ApplicationListener接口的listenerBeanNames集合,并添加到事件多播器的defaultRetriever.applicationListenerBeans中。
2.3.3 接着将早期存储的earlyApplicationEvents事件集合通过事件多播器的multicastEvent方法发布事件,将容器的earlyApplicationEvents设置为null。
2.3.4 查看ApplicationEventMulticaster的multicastEvent方法,先获取到event事件的类型type,接着调用getApplicationListeners方法获取可以监听该事件event的监听器集合。
2.3.5 在getApplicationListeners方法中,先判断事件多播器的retrieverCache缓存中是否可以找到该事件的监听器集合。若是找到,则直接返回缓存中的监听器集合。
若是找不到,则接着通过retrieveApplicationListeners方法找到可以监听该事件的监听器集合并返回。
2.3.6 在retrieveApplicationListeners方法中,先遍历listeners(defaultRetriever.applicationListeners), 通过supportsEvent方法判断该监听器是否可以监听该事件,若可以,则加入到allListeners集合中。
2.3.6.1 在supportsEvent方法中,先判断监听器是否实现了GenericApplicationListener接口。
若是实现了,则将监听器转换成GenericApplicationListener赋值给smartListener,如ApplicationListenerMethodAdapter(标识@EventListener的方法生成的监听器)实现该接口。
而实现ApplicationListener接口的监听器没实现该接口,所以通过创建GenericApplicationListenerAdapter赋值给smartListener,然后调用GenericApplicationListener的supportsEventType方法。
2.3.6.2 GenericApplicationListener接口实现类如下图。
GenericApplicationListenerAdapter的构造器中,通过resolveDeclaredEventType方法解析监听器,得到监听器可以监听事件的类型。
在GenericApplicationListenerAdapter的supportsEventType中,通过isAssignableFrom方法判断eventType监听事件的类型是否是监听器监听事件的类型本身或实现类(继承或实现了监听器监听事件的类型)。若是,则表示该监听器可以监听此事件。
2.3.7 接着listenerBeans集合若是不为空,接着遍历listenerBeans集合,判断allListeners集合是否包含遍历的监听器对象。若是不包含,则通过supportsEvent方法判断监听器是否可以监听该事件,若可以,则将其添加到allListeners集合, 最后返回allListeners集合。
2.3.8 遍历返回的监听器集合,判断事件多播器是否有Executor类型的异步对象。若是有,则通过异步对象异步运行invokeListener方法去运行监听器的onApplicationEvent方法,若是没有,则同步运行监听器的invokeListener方法。
2.4 容器通过preInstantiateSingletons方法,创建并初始化完所有非延迟加载的单实例组件对象后,接着遍历容器的beanDefinitions集合,找到实现SmartInitializingSingleton接口的单实例对象,调用对象的afterSingletonsInstantiated方法。
2.4.1 EventListenerMethodProcessor处理器实现SmartInitializingSingleton接口,该处理器主要是解析@EventListener注解,通过afterSingletonsInstantiated方法的processBean方法将标识@EventListener注解的方法封装成ApplicationListenerMethodAdapter的监听器对象并加入到多播器中。
参考分析事件监听器注解:@EventListener、@TransactionalEventListener_Just-Today的博客-优快云博客
2.5 通过容器发布事件,调用容器的publishEvent方法,参数可以是ApplicationEvent、Object或它们的子类。
统一调用了publishEvent(Object event, @Nullable ResolvableType eventType)方法,在该方法中,先判断event是否实现了ApplicationEvent接口,若是有,则转换成ApplicationEvent。若是没有,event则通过创建PayloadApplicationEvent对象来构建ApplicationEvent。
接着调用多播器的multicastEvent方法发布事件,流程就是2.3.4节。
参考分析事件监听器注解:@EventListener、@TransactionalEventListener_Just-Today的博客-优快云博客