目标:
1. 监听器如何使用
2. 监听器的原理
3. 监听器的类型
4. 多播器的概念和作用
5. 接口类型的监听器是如何注册的?
6. 注解类型的监听器和如何注册的?
7. 如果想在所有的bean都加载完成以后做一些事情,怎么办?
?
?一.?监听器的使用
为什么要学习监听器呢?学习监听器主要学习监听器的设计思想。 比如,我们之前研究过的nacos,他就是使用监听器进行集成的。所以了解监听器的原理,就很重要了。
首先, 我们要知道监听器如何使用。?
1.1 Spring事件的原理
原理: 是观察者模式
Spring的事件监听有三个组成部分:
1. 事件(ApplicationEvent):要广播,发送的消息. 监听器监听的事情
2. 监听器(ApplicationListener): 观察者模式中的观察者,监听器监听特定事件,并在内部定义了事件发生后的相应逻辑.
3. 事件发布器(ApplicationEventMulticaster):对应于观察者模式中的被观察者/主题.负责通知观察者. 对外提供发布事件和增删事件监听器的接口.维护事件和事件监听器之间的关系.并在事件发生时负责通知事件监听器.
?
1.2 认识监听器
上面认识了监听器. 接下来看一个例子. 通过例子来理解.
就好比现在有一个消息,比如说: 下单后减库存. 减库存就是一个事件,这个事件需要一个事件播放器,将事件播放出去. 然后另一端事件监听器,接收到信息,进行处理.
比如:下面的demo
有一个订单Order :
package com.lxl.www.events;
/**
* Description
*
* DATE 2020/11/17.
*
* @author lxl.
*/
public class Order {
private Integer id;
public Integer getId() {
return id;
}
void setId(Integer id) {
this.id = id;
}
}
接下来,有一个订单事件. 订单的操作,带来的库存的增减. 就是一个订单事件
package com.lxl.www.events;
import org.springframework.context.ApplicationEvent;
import java.io.Serializable;
*
* Description
* 订单的事件
*
* 事件的分类: 分为自定义事件和内置事件
* DATE 2020/11/17.
*
* @author lxl.
OrderEvent extends ApplicationEvent implements Serializable {
private static final long serialVersionUID = 1L;
String name;
public OrderEvent(Object event,String name) {
super();
this.name = name;
}
String getName() {
setName(String name) {
name;
}
}
第三: 事件监听器,事件监听器用来监听事件. 当OrderEvent发布减库存消息的时候,事件监听器就能听到.
package com.lxl.www.events;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
*
* Description
* OrderEvent的事件监听器
*
*
* DATE 2020/11/17.
*
* @author lxl.
*/
@Component
class OrderEventListenter implements ApplicationListener<OrderEvent> {
*
* 当某一个事件发布的时候,就会触发事件监听器
* @param event the event to respond to
@Override
void onApplicationEvent(OrderEvent ) {
if (event.getName().equals("减库存")) {
System.out.println(事件监听器 监听到 减库存);
}
}
}
是不是和mq相差不多.
mq也是一个订阅者,一个发布者.?
下面写一个main方法,运行看看监听器的效果
package com.lxl.www.events;
import org.springframework.beans.factory.parsing.SourceExtractor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
*
* 监听器的使用
MainClass {
static main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.);
*
* 使用场景: 比如有一个订单,由用户下单了,那么对应的就要减库存.其实下单和减库存不需要是串行.
* 通常,我们会使用一个mq去处理减库存的情况. 也就是采用异步的方式.
*
* 那么,监听器的远离和mq是类似的. 我们可以手动设置采用同步还是异步的方式处理.
Order order = new Order();
order.setId(1);
System.下单// 发布事件. 当在这里发布事件,那么就会被事件监听器监听到
ctx.publishEvent(new OrderEvent(order,));
System.日志.....);
}
}
输出结果
下单
事件监听器 监听到 减库存
日志.....
监听器使用的设计模式是: 观察者模式.
?
1.3 监听器的类型
监听器有两种类型: 一种是内置的监听器,一种是自定义监听器.?
1.3.1 内置监听器
?spring设置了一个内置监听器的父类.
abstract ApplicationContextEvent extends ApplicationEvent {
*
* Create a new ContextStartedEvent.
* @param source the {@code ApplicationContext} that the event is raised for
* (must not be {@code null})
*/
ApplicationContextEvent(ApplicationContext source) {
super(source);
}
*
* Get the {@code ApplicationContext} that the event was raised for.
final ApplicationContext getApplicationContext() {
(ApplicationContext) getSource();
}
}
实现了ApplicationContextEvent的类就是内置的监听器. 我们使用快捷键ctrl + H,查看都有哪些类实现了 ApplicationContextEvent
? 
一共有5各类实现了ApplicationContextEvent.??
|
Event
说明
ContextRefreshEvent
当容器被实例化或者refresh时发布.如调用refresh()方法. 此处的实例化是指所有的bean都已被加载,后置处理器都被激活,所有单例bean都已被实例化,所有的容器对象
都已经准备好可使用. 如果容器支持热重载,则refresh()可以被触发多次(XmlWebApplicationContext支持热刷新,而GenericApplicationContext不支持热刷新)
ContextStartedEvent
当容器启动时发布,即调用start()方法,已启用意味着所有的lifecycle都已显示收到了start的信号
ContextStoppedEvent
当容器停止时发布. 即调用stop()方法,既所有的lifecycle bean都已显示接收了stop信号,关闭的容器可以通过start()方法重启
ContextClosedEvent
当容器关闭时发布. 即调用close()方法,关闭意味着所有的单例bean都已被销毁. 关闭的容器不能被重启或refresh()
?
?1.?ContextRefreshEvent:?当容器被实例化或者refresh时发布
我们来看看一下源码.
从refresh()源码进入.
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
进入构造函数,首先调用自身的构造方法this();
调用自身的构造方法之前,要先调用父类的构造方法
this();
register配置注册类
register(componentClasses);
// ioc容器刷新接口--非常重要
refresh();
}
*
* refresh是spring最核心的方法,里面包含了整个spring ioc的全过程,包括spring加载bean到销毁bean的全过程
* 学习spring,就是学习里面的13个方法,如果13个方法都学完了,基本上就打通了
* @throws BeansException
* @throws IllegalStateException
refresh() throws BeansException,IllegalStateException {
synchronized (.startupShutdownMonitor) {
1. 准备刷新上下文环境
prepareRefresh();
Tell the subclass to refresh the internal bean factory.
2. 获取告诉子类初始化bean工厂,不同工厂不同实现
ConfigurableListablebeanfactory beanfactory = obtainFreshbeanfactory();
......
Last step: publish corresponding event.
//最后容器刷新 发布刷新时间(spring cloud是从这里启动的 )
finishRefresh();
}
......
}
}
进入到finishRefresh()方法
protected finishRefresh() {
Clear context-level resource caches (such as ASM Metadata from scanning).
清除上下文缓存
clearResourceCaches();
Initialize lifecycle processor for this context.
注册lifecycleProcessor声明周期处理器
作用: 当ApplicationContext启动或停止时,他会通过LifecycleProcessor来与所有声明的bean进行交互
initLifecycleProcessor();
Propagate refresh to lifecycle processor first.
为实现了SmartLifeCycle并且isAutoStartup,自动启动的Lifecycle调用start()方法
getLifecycleProcessor().onRefresh();
// 发布容器启动完毕事件
publishEvent(new ContextRefreshedEvent(this));
Participate in LiveBeansView MBean,if active.
LiveBeansView.registerApplicationContext();
}
我们看到有一个发布事件. 这个事件的作用是通知容器已经启动完毕. 注意看,里面发布的是什么事件??new ContextRefreshedEvent(this).?发布的是ContextRefreshedEvent事件.
下面有一个问题:??怎么样可以在所有的bean创建完以后做扩展代码呢?
上面我们说到了,当所有的bean都创建完以后,会调用publishEvent(new ContextRefreshedEvent(this));发布容器启动完毕的事件.
这时我们可以自定义一个监听器,用来监听ContextRefreshedEvent事件.
*
* 自定义一个事件监听器,用来监听ContextRefreshedEvent事件
ContextRefreshedEventListener {
*
* 声明这是一个事件监听器,监听的是ContextRefreshedEvent事件.
* @param event
@EventListener(ContextRefreshedEvent.)
void onApplicationEvent(ContextRefreshedEvent ) {
....
在所有的bean创建完以后,写一些逻辑代码
}
}
然后,在里面写上我们需要在容器都创建完毕之后执行的逻辑代码.
?
2.?ContextClosedEvent:?当容器关闭时发布
还是先来看源码,spring是在何时发布的这个事件.
doClose() {
Check whether an actual close attempt is necessary...
this.active.get() && this.closed.compareAndSet(false,true)) {
if (logger.isDebugEnabled()) {
logger.debug(Closing " + );
}
LiveBeansView.unregisterApplicationContext();
try {
// Publish shutdown event.
publishEvent(new ContextClosedEvent(this));
}
catch (Throwable ex) {
logger.warn(Exception thrown from ApplicationListener handling ContextClosedEvent Stop all Lifecycle beans,to avoid delays during individual destruction.
this.lifecycleProcessor != null) {
{
.lifecycleProcessor.onClose();
}
(Throwable ex) {
logger.warn(Exception thrown from LifecycleProcessor on context close Destroy all cached singletons in the context's beanfactory.
destroyBeans();
Close the state of this context itself.
closebeanfactory();
Let subclasses do some final clean-up if they wish...
onClose();
Reset local application listeners to pre-refresh state.
this.earlyApplicationListeners != .applicationListeners.clear();
this.applicationListeners.addAll(.earlyApplicationListeners);
}
Switch to inactive.
set(false);
}
}
在doClose()的时候,发布了publishEvent(new ContextClosedEvent(this));事件
我们看一看具体发布的是什么事件呢? 就是ContextClosedEvent事件
假如: 我们想要在容器关闭的时候做一些扩展,就可以写一个监听器,在容器关闭的时候监听ContextClosedEvent事件
??
?Spring内置的事件,我们就不用再自己定义了. 我们需要做的就是定义一个监听器,监听事件就可以了.
?
?1.3.2 自定义监听器
不是spring定义的监听器,也就是我们自己定义的监听器就是自定义监听器. 下面来看看自定义监听器的两种类型.?
类型一:?基于接口?
@Component
class HelloEventListener implements ApplicationListener<OrderEvent> {
@Override
) {
)) {
System.减库存....);
}
}
}
事件监听器需要实现ApplicationListener接口,这是一个泛型接口,泛型的类型就是事件的类型.
其次,这个监听器需要是spring容器托管的bean,因此加上了@Component注解,里面只有一个方法onApplicationEvent,就是事件触发时执行的内容.?
类型二: 基于注解
OrderEventListener {
@EventListener(OrderEvent.class)
) {
)) {
System.);
}
}
}?
在方法上面添加注解@EventListener(OrderEvent.class) 监听的是哪个事件呢?OrderEvent.class
?我们在定义监听器的时候,可以选择是基于接口的方式还是基于注解的方式.
?二. 监听器源码
?首先,监听器的声明,调用,都是在refresh()方法里面进行,我们先来看看refresh()的整体脉络. 其中标红的部分是和监听器有关系的模块.
?

?这里面的第五步,第九步,第十一步,都详细的分析过. 下面主要看看和监听器有关的几步.
?2.1 准备上下文环境prepareRefresh()
在准备上下文环境的时候,我们看看做了哪些事情

?
?1. 设置了容器当期的状态,是激活状态
2. 初始化了属性源initPropertySources();.
在AbstractApplicationContext类中没有实现这个方法. 这是一个父类定义的方法. 比如:我们可以自定义一个类,然后重写initPropertySource,在改方法中设置一个环境变量abc,那么在容器启动的时候,就会去环境变量中检查,是否环境变量中有这个属性,如果没有就会抛出异常.
3. 接下来就是验证上面环境变量中指定的属性是否存在了. getEnvironment().validaterequiredProperties(); 不存在就抛出异常MissingrequiredPropertiesException
4. 然后接下来,和事件有关的一步,创建了早期的事件监听器
创建早期的事件监听器.
Store pre-refresh ApplicationListeners...
this.earlyApplicationListeners == ) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
.applicationListeners.clear();
.earlyApplicationListeners);
}
这里有一个问题,什么是早期的事件监听器呢? 早对应的就是晚了. 早期指的是多早呢?
早期事件指的是事件监听器还没有注册到事件多播器的时候.
早期定义的事件不需要手动的publishEvent,在RegisterListener()阶段会自动发布早期事件.
什么是早期的事件监听器呢? 早对应的就是晚了. 早期指的是多早呢?
早期事件指的是事件监听器还没有注册到事件多播器的时候.
早期定义的事件不需要手动的publishEvent,在RegisterListener()阶段会自动发布早期事件.
在这里就定义了一个集合,这个集合就是后面事件监听器集合. 在这里只是进行的初始化
?
5. 初始化保存早期事件的集合
this.earlyApplicationEvents = new LinkedHashSet<>();
在第一步: 对事件的操作就是初始化. 一共初始化了两个集合,一个是早期事件监听器集合,一个是早期的事件集合
?
2.2 初始化bean工厂?
?我们现在经常使用的beanfactory有两种,一种是xml方式的,另一种是注解方式的. 其实使用注解的更多一些. xml和注解方式的bean工厂在初始化的时候也是有区别的.?

?从上图可以看出,获取两种方式的bean工厂的区别
1. AbstractRefreshableApplicationContext: 基于xml配置文件的方式
2. GenericApplicationContext: 基于注解的方式.
基于注解实现的里面代码很简单,只是刷新的beanfactory. 没有耦合加载beanDefinition的流程.
基于xml实现的代码,里面耦合了加载beanDefinition
先来看看基于注解方式的,基于注解方式只是指定了bean工厂的序列化ID
@Override
protected final refreshbeanfactory() throws IllegalStateException {
if (!this.refreshed.compareAndSet(throw IllegalStateException(
GenericApplicationContext does not support multiple refresh attempts:
just call 'refresh' once);
}
// 指定bean工厂的序列化ID
this.beanfactory.setSerializationId(getId());
}
再来看看基于xml方式的,基于xml方式的 除了指定了bean工厂的序列化id,还耦合加载了beanDefinition
refreshbeanfactory() throws BeansException {
判断bean工厂是否初始化过,如果已经初始化过那么销毁并关闭
(hasbeanfactory()) {
destroyBeans();
closebeanfactory();
}
重新创建一个bean工厂
DefaultListablebeanfactory beanfactory = createbeanfactory();
设置序列化id
beanfactory.setSerializationId(getId());
设置个性化属性
customizebeanfactory(beanfactory);
// 加载BeanDefinition
loadBeanDefinitions(beanfactory);
this.beanfactory = beanfactory;
}
(IOException ex) {
new ApplicationContextException(I/O error parsing bean definition source for " +
getDisplayName(),ex);
}
}
?看上面的步骤.?
1. 先看看是否已经有过工厂了,如果已经有了,那么销毁,关闭
2. 重新创建了一个空的新的工厂
3. 设置新工厂的序列化id
4. 设置个性化属性bean
5. 加载bean定义. 我们看到,使用xml方式会加载bean定义
6. 返回bean工厂对象
这一步: 主要是初始化了bean工厂
?
2.3?对bean工厂进行填充属性preparebeanfactory(beanfactory);

?这一步是和监听器有关系的. 我们先来看看源码
preparebeanfactory(ConfigurableListablebeanfactory beanfactory) {
Tell the internal bean factory to use the context's class loader etc.
设置bean工厂的类加载器为当前的application应用的加载器
beanfactory.setBeanClassLoader(getClassLoader());
为bean工厂设置标准的SPEL表达式解析器对象(StandardBeanExpressionResolver)
beanfactory.setBeanExpressionResolver( StandardBeanExpressionResolver(beanfactory.getBeanClassLoader()));
为bean工厂设置一个PropertiesEditor属性资源编辑器(用于后面给bean对象赋值)
beanfactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar( Configure the bean factory with context callbacks.
*
* 注册一个完整的ApplicationContextAwareProcessor后置处理器,用来处理ApplicationContextAware
* ApplicationContextAwareProcessor是一个bean的后置处理器. 怎么使用呢?
*
* 在bean初始化完成以后,会调用一堆的bean后置处理器.
* 在初始化的地方,其实只调用了三个bean后置处理器. 那么其他的后置处理器是什么时候调用的呢?
* 就是在这里,这里注册了 ApplicationContextAwareProcessor.
* 在ApplicationContextAwareProcessor#invokeAwareInterfaces方法里调用了其他的aware
* 那么invokeAwareInterfaces方法是在哪里调用呢?
* 是在ApplicationContextAwareProcessor#postProcessBeforeInitialization调用的
* postProcessBeforeInitialization是在bean初始化之前会调用的后置处理器
*
* 然后在通过addBeanPostProcessor()方法,将bean的后置处理器添加到beanPostProcessors集合中
*/
beanfactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
*
* 忽略部分接口的函数方法,在populateBean(创建bean的第二步:属性赋值)时
* 因为下面接口都有set***方法,这些方法不特殊处理将会自动注入到容器中.
*
* 忽略了这么多的Aware,这是怎么回事呢? 因为Aware里面的方法都是以set开头的. 当在创建bean,设置属性的时候,* 会给带有set+属性名的方法赋值. 而Aware的这些方法要忽略掉,为什么忽略掉呢?
*
* 比如:EnvironmentAware 里面设置了一些环境变量,这些环境变量是不需要进行属性装配的,所以要把他们排除掉
beanfactory.ignoreDependencyInterface(EnvironmentAware.);
beanfactory.ignoreDependencyInterface(EmbeddedValueResolverAware.);
beanfactory.ignoreDependencyInterface(ResourceLoaderAware.);
beanfactory.ignoreDependencyInterface(ApplicationEventPublisherAware.);
beanfactory.ignoreDependencyInterface(MessageSourceAware.);
beanfactory.ignoreDependencyInterface(ApplicationContextAware. beanfactory interface not registered as resolvable type in a plain factory.
MessageSource registered (and found for autowiring) as a bean.
*
* 将beanfactory类型的实例注册解析
*
* 当注册了依赖解析以后,例如当注册了对beanfactory.class的解析依赖后,* 当bean属性注入的时候,一旦检测到属性为beanfactory类型. 便会将beanfactory的实例注册解析
* 为什么呢?
* 比如:
* @Autowired
* ApplicationContext applicationContext 为什么能够自动装配,通过@Autowired引入呢? 就是在这里装配的.
* 这个也是在注入属性popularBean的时候体现的
*
beanfactory.registerResolvableDependency(beanfactory.class,1)">);
beanfactory.registerResolvableDependency(ApplicationEventPublisher.);
beanfactory.registerResolvableDependency(ApplicationContext. Register early post-processor for detecting inner beans as ApplicationListeners.
// 注册事件监听器探测器后置处理器接口,ApplicationListenerDetector 解析接口方式的监听器
beanfactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
Detect a LoadTimeWeaver and prepare for weaving,if found.
(beanfactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanfactory.addBeanPostProcessor( LoadTimeWeaverAwareProcessor(beanfactory));
Set a temporary ClassLoader for type matching.
beanfactory.setTempClassLoader( ContextTypeMatchClassLoader(beanfactory.getBeanClassLoader()));
}
Register default environment beans.
beanfactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanfactory.registerSingleton(ENVIRONMENT_BEAN_NAME,getEnvironment());
}
beanfactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanfactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME,getEnvironment().getSystemProperties());
}
beanfactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanfactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME,getEnvironment().getSystemEnvironment());
}
}
1.?设置bean工厂的类加载器为: 当前的application应用的加载器
2.?为bean工厂设置标准的SPEL表达式解析器对象,这个解析器对象是谁呢? 就是StandardBeanExpressionResolver
3.?为bean工厂设置一个PropertiesEditor属性资源编辑器,用于后面给bean对象赋值
4. 给bean工厂注册了一个ApplicationContextAwareProcessor后置处理器. 这里说说这个后置处理器类. 这个类有什么作用呢?
在bean初始化完成以后,会调用一堆的bean后置处理器
在doCreateBean()中找到第三步: 初始化bean
protected Object initializeBean(final String beanName,final Object bean,@Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != ) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
在初始化完成以后,调用aware
invokeAwareMethods(beanName,bean);
return ;
},getAccessControlContext());
}
{
// 在初始化的时候,会调用很多的aware.
invokeAwareMethods(beanName,bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
在初始化之前调用bean的后置处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean,beanName);
}
调用初始化方法
invokeInitMethods(beanName,wrappedBean,mbd);
}
(Throwable ex) {
BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : ),beanName,Invocation of init method Failed 再初始化之后调用bean的后置处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean,1)"> wrappedBean;
}
我们看到,在初始化bean的时候,调了很多Aware,?invokeAwareMethods(beanName,bean);
*
* 这里主要有三类aware
* @param beanName
* @param bean
invokeAwareMethods(final String beanName,final Object bean) {
*
* 在这里调用的aware只有三类,我们去beanfactory中看,他有一大堆的aware要调用,* 那么其他的aware是在哪里调用的呢?
*/
(bean instanceof Aware) {
实现了BeanNameAware的bean
(bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
实现了BeanClassLoaderAware接口
BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != ) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
实现了beanfactoryAware
beanfactoryAware) {
((beanfactoryAware) bean).setbeanfactory(AbstractAutowireCapablebeanfactory.);
}
}
}
如上代码,我们看到,其实知道用了3中类型的Aware. 分别是BeanNameAware,BeanClassLoaderAware 和 beanfactoryAware.
那么其他的Aware呢? 我们看beanfactory接口的注释可以看到,会调用很多Aware

?
在初始化的地方,其实只调用了三个bean后置处理器. 那么其他的后置处理器是什么时候调用的呢?
就是在这里,这里注册了 ApplicationContextAwareProcessor.
在ApplicationContextAwareProcessor#invokeAwareInterfaces方法里调用了其他的aware
*
* 判断bean是否实现了各种Aware
* @param bean
invokeAwareInterfaces(Object bean) {
(bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(.applicationContext.getEnvironment());
}
(bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(.embeddedValueResolver);
}
(bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(.applicationContext);
}
ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher( (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource( (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(.applicationContext);
}
}
?而这个方法,什么时候执行呢? 在初始化之前调用Bean的后置处理器执行的ApplicationContextAwareProcessor#postProcessBeforeInitialization
@Override
@Nullable
postProcessBeforeInitialization(Object bean,String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
bean;
}
AccessControlContext acc = ;
) {
acc = .applicationContext.getbeanfactory().getAccessControlContext();
}
if (acc != {
invokeAwareInterfaces(bean);
{
invokeAwareInterfaces(bean);
}
bean;
}
?然后在通过addBeanPostProcessor()方法,将bean的后置处理器添加到beanPostProcessors集合中.
5. 忽略部分接口的函数方法. 这些接口主要是Aware.??
beanfactory.ignoreDependencyInterface(EnvironmentAware.class);
beanfactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanfactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanfactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanfactory.ignoreDependencyInterface(MessageSourceAware.class);
beanfactory.ignoreDependencyInterface(ApplicationContextAware.class);
?忽略了这么多的Aware,这是怎么回事呢?为什么忽略掉呢? 因为Aware里面的方法都是以set开头的. 当在创建bean,
会给带有set+属性名的方法赋值.在populateBean(创建bean的第二步:属性赋值)时 因为下面接口都有set***方法,这些方法不特殊处理将会自动注入到容器中.
比如:EnvironmentAware 里面设置了一些环境变量,所以要把他们排除掉
6.?将beanfactory类型的实例注册解析
beanfactory.registerResolvableDependency(beanfactory.class,beanfactory);
beanfactory.registerResolvableDependency(ResourceLoader.class,this);
beanfactory.registerResolvableDependency(ApplicationEventPublisher.class,this);
beanfactory.registerResolvableDependency(ApplicationContext.class,this);
当注册了依赖解析以后,
当bean属性注入的时候,一旦检测到属性为beanfactory类型. 便会将beanfactory的实例注册解析
为什么呢?
比如:
@Autowired
ApplicationContext applicationContext; .
为什么能够自动装配,通过@Autowired引入呢? 就是在这里装配的
这个也是在注入属性popularBean的时候体现的
7.?注册了一个解析接口方式的监听器的 BeanPostProcessor.?
beanfactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
我们来看看ApplicationListenerDetector?类,其下的?postProcessAfterInitialization方法,是在createBean的第三步初始化之后执行的bean的后置处理器.
@Override
Object postProcessAfterInitialization(Object bean,String beanName) {
if (bean instanceof ApplicationListener) {
potentially not detected as a listener by getBeanNamesForType retrieval
Boolean flag = this.singletonNames.get(beanName);
(Boolean.TRUE.equals(flag)) {
singleton bean (top-level or inner): register on the fly
* 注册接口类型的监听器. 将其添加到applicationContext中
* 之所以要在这里在加一次,是为了处理懒加载情况
*/
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
}
else (Boolean.FALSE.equals(flag)) {
这里是处理早期事件.
if (logger.isWarnEnabled() && !.applicationContext.containsBean(beanName)) {
inner bean with other scope - can't reliably process events
logger.warn(Inner bean '" + beanName + ' implements ApplicationListener interface " +
but is not reachable for event multicasting by its containing ApplicationContext because it does not have singleton scope. Only top-level listener beans are allowed to be of non-singleton scope.);
}
.singletonNames.remove(beanName);
}
}
bean;
}
我们看这个方法,方法一进来就判断,是否是实现了ApplicationListener接口. 也就是说,上面我们输了注册监听器有两种方式,一种是接口方式,另一种是注解方式. 这里解析的是实现接口的方式.
在这里,我们要先建立一个印象,因为后面还会说到他. 为什么呢? 因为接口方式的监听器在两个地方被调用,一个是这里,另一个是在refresh()后面的流程registerListener()的时候. 那么,为什么要有两次调用监听器呢? 我们后面再说
2.4?postProcessbeanfactory(beanfactory); 这是一个扩展方法,可以初始化剩余的Aware.?
我们是AbstractApplicationContext没有实现,但AbstractRefreshableWebApplicationContext类. 里面就定义了postProcessbeanfactory(beanfactory)
在里面注册了ServletContextAwareProcessor
beanfactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext,this.servletConfig));
beanfactory.ignoreDependencyInterface(ServletContextAware.class);
beanfactory.ignoreDependencyInterface(ServletConfigAware.class);
上面我们知道在 beanfactory 里定义了需要调用的很多Aware. 但是有几个Aware还没有说到.
比如: ServletContextAware's {@code setServletContext} : ServletContextAware,可以获得当前的ServletContextAware
添加了这个Aware以后,我们就可以实现一个ServletContextAware的接口.
到这里,我们就知道所有的aware都在哪里被调用了.
2.5?调用bean工厂的后置处理器,解析配置类
?这一步就略过了,之前重点说过这一步
2.6?registerBeanPostProcessors(beanfactory);?注册bean后置处理器,这里主要是和AOP有关系
这里和监听器关系不太大,也暂时略过
2.7??initMessageSource();?初始化国际化资源处理器
2.8?initApplicationEventMulticaster();创建事件多播器
?事件多播器管理所有的事件监听器. 并广播事件给对应的监听器
当我们调用ctx.publishEvent())的时候. 就会去通知所有监听了OrderEvent事件的事件监听器,那么,是由谁去负责通知呢?
就是由EventMulticaster(事件多播器)将事件播报出去的.

?首先,判断有没有最定义的事件多播器. 如果有,那么直接将其添加到容器中. 如果没有,就新建一个SimpleApplicationEventMulticaster类型的事件多播器,然后将其添加到beanfactory中.
那么,事件多播器都做了什么事情呢? 具体来看一看SimpleApplicationEventMulticaster类.?

?这是SimpleApplicationEventMulticaster的继承结构. 继承了AbstractApplicationEventMulticaster,而AbstractApplicationEventMulticaster又实现了ApplicationEventMulticaster. 我们看看在ApplicationEventMulticaster中都对应了哪些接口
interface ApplicationEventMulticaster {
void addApplicationListener(ApplicationListener<?> listener);
addApplicationListenerBean(String listenerBeanName);
void removeApplicationListener(ApplicationListener<?> removeApplicationListenerBean(String listenerBeanName);
removeAllListeners();
void multicastEvent(ApplicationEvent );
*
* AbstractApplicationEventMulticaster管理了所有的监听器.
* 当我们注册一个监听器以后,就会通过addApplicationListener方法添加到事件多播器中.
* @param listener the listener to add
void addApplicationListener(ApplicationListener<?> listener) {
synchronized (.retrievalMutex) {
Explicitly remove target for a proxy,if registered already, in order to avoid double invocations of the same listener.
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
(singletonTarget instanceof ApplicationListener) {
.defaultRetriever.applicationListeners.remove(singletonTarget);
}
.defaultRetriever.applicationListeners.add(listener);
.retrieverCache.clear();
}
}
?这是添加事件监听器.
在SimpleApplicationEventMulticaster里面,定义了广播事件监听器
void multicastEvent(final ApplicationEvent null ? eventType : resolveDefaultEventType());
获取线程池
Executor executor = getTaskExecutor();
从多播器中获取所有的监听器
for (ApplicationListener<?> listener : getApplicationListeners( 拿到了监听器
if (executor != 异步调用广播事件
executor.execute(() -> invokeListener(listener,1)">));
}
// 同步调用广播事件
invokeListener(listener,event);
}
}
}
?这里有两种方式,一种是同步的方式,另一种是异步的方式. 根据设置的eventType来决定的. 其实异步的方式就是建立了一个新的线程
我么你来看一下调用事件监听器广播事件
invokeListener#doInvokeListener
doInvokeListener(ApplicationListener listener,ApplicationEvent // 最终调用的是监听器的onApplicationEvent方法. 这个方法就是每一个监听器都会自定义的方法.
listener.onApplicationEvent(event);
}
(ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg,1)">.getClass())) {
Possibly a lambda-defined listener which we could not resolve the generic event type for
-> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
(logger.isTraceEnabled()) {
logger.trace(Non-matching event type for listener: listener,ex);
}
}
throw ex;
}
}
}
?最终调用的是监听器的onApplicationEvent方法. 这个方法就是每一个监听器都会自定义的方法.
listener.onApplicationEvent(event);
?2.9?onRefresh();这是一个扩展方法. 这里没有具体实现.spring boot也是从这个方法进行启动
2.10 注册监听器registerListeners();

?注册监听器这里一共做了三件事:
1. 将事件监听器注册到多播器上
2. 广播早期的事件
3. 清空早期事件.
到此步骤之前,上面都是有早期事件的,后面就没有早期事件了,因为这一步就都清空了. 后面也不会在进行自动广播了,?自动广播的就是早期事件.
registerListeners() {
Register statically specified listeners first.
/**
* 第一步,获取所有的事件监听器集合.
* 通常,这个时候,事件监听器集合是空的,除非手动调用allApplicationListeners()注册事件监听器
*/
for (ApplicationListener<?> listener : getApplicationListeners()) {
将监听器注册到多播器上
getApplicationEventMulticaster().addApplicationListener(listener);
}
/**
* 第二步: 注册接口方式的监听器
* 获取beanDefinition中 ApplicationListener 类型的监听器. 也就是说,使用接口方式定义的监听器
* 就可以在这里被注册到多播器的
* 这里是从BeanDefinition中拿的,我们自定义了 OrderEventListenter 监听器,那么会不会拿到呢?
* 我们知道监听器的实现有两种方式,一种是注解方式.
* 如果OrderEventListenter采用的是接口方式,那么就可以拿到. 因为它实现了ApplicationListener.拿到了,
* 就把监听器注册到多播器上.
* 如果是注解方式,那就拿不到了
*
*/
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.true,1)">);
for (String listenerBeanName : listenerBeanNames) {
把监听器注册到多播器上
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
/**
* 第三步: 获取早期的事件,然后广播早期事件.
* 这些早期事件是在第一步 prepareRefresh 注册的.
*
*/
Set<ApplicationEvent> earlyEventsToProcess = .earlyApplicationEvents;
在这里将早期事件清空,清空完以后,就没有早期事件了.
this.earlyApplicationEvents = ;
CollectionUtils.isEmpty(earlyEventsToProcess)) {
(ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
如上源码所示:?
第一步. 获取所有的事件监听器集合,通常这个时候,事件监听器的集合都是空的,除非我们手动调用allApplicationListeners()注册事件监听器
第二步: 注册接口方式的监听器. 注意,是接口方式的. 通常我们自定义的监听器.? 有两种类型,接口方式和注解方式. 如果使用的是接口方式. 那么就是在这里被注册的.如果是注解方式.不在这里注册.
getBeanNamesForType(ApplicationListener.class,true,false);
扫描获取ApplicationListener类型的监听器.
然后将其注册到多播器上. 我们知道多播器的两个主要功能,管理监听器和广播事件.
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
第三步: 获取早期事件,然后广播早期事件. 早期事件我们之前已经说过了,是在第一步prepareRefresh()方法里注册的.
随后,立即清空早期事件集合. 然后广播事件. 这样早期定义好的事件就都被广播出去了,并且只能执行一次,不会被再次执行.
*
* 第三步: 获取早期的事件,然后广播早期事件.
* 这些早期事件是在第一步 prepareRefresh 注册的.
*
Set<ApplicationEvent> earlyEventsToProcess = .earlyApplicationEvents;
;
CollectionUtils.isEmpty(earlyEventsToProcess)) {
(ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
2.11?实例化剩余的单实例bean
?这个方法就是循环遍历BeanDefinitionMap,调用getBean,去生产剩余的bean,之前详细研究过这个步骤,这里就不说了
2.12 完成refresh()操作,?发布刷新事件?
finishRefresh() {
Clear context-level resource caches (such as ASM Metadata from scanning).
clearResourceCaches();
Initialize lifecycle processor for this context.
注册lifecycleProcessor声明周期处理器
initLifecycleProcessor();
Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
// 发布容器refresh完毕的事件.
// 发布的是什么事件呢? 是ContextRefreshedEvent事件.
publishEvent(new ContextRefreshedEvent(this));
);
}
在这一步: 发布了容器Refreshed事件. 也就是容器启动完成的事件.?
到这里,我们来看看publicshEvent的具体实现
*
* 发布事件给所有的监听器
* Publish the given event to all listeners.
* @param event the event to publish (may be an {@link ApplicationEvent}
* or a payload object to be turned into a {@link PayloadApplicationEvent})
* @param eventType the resolved event type,if known
* @since 4.2
void publishEvent(Object event,1)">Event must not be null Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
/**
* 第一步: 获取事件
*/
instanceof ApplicationEvent) {
处理接口类型的事件
applicationEvent = (ApplicationEvent) ;
}
{
applicationEvent = new PayloadApplicationEvent<>(this,1)">);
if (eventType == ) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
/**
* 第二步: 发布事件
*/
Multicast right now if possible - or lazily once the multicaster is initialized
this.earlyApplicationEvents != ) {
.earlyApplicationEvents.add(applicationEvent);
}
* 调用事件多播器,将这个事件发布出去
* 事件多播器是什么时候注册的呢?
* 就是在refresh()初始化的时候,调用initApplicationEventMulticaster(); 初始化的事件多播器
getApplicationEventMulticaster().multicastEvent(applicationEvent,eventType);
}
/**
* 第三步: 发布事件给父类容器
*/
Publish event via parent context as well...
发布事件给父类容器
this.parent != .parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event,eventType);
}
{
this.parent.publishEvent();
}
}
}
这里做了如下几件事
1. 获取事件
2. 广播事件
3. 广播事件给父类监听器.
详细代码可以看注释
接下来看一下,具体的multicastEvent(...)
void multicastEvent(final ApplicationEvent ));
获取线程池
Executor executor = 从多播器中获取所有的监听器
拿到了监听器
) {
// 异步调用广播事件
executor.execute(() -> invokeListener(listener,1)">// 同步调用广播事件
invokeListener(listener,1)">);
}
}
}
这里首先会去获取线程池. 看看有没有重新定义线程池,如果有这里executor就不是空的.
广播事件有两种形式,?一种是同步,一种是异步.?如果executor线程池不空,就以异步的形式广播,否则就以同步的形式广播.?
那么,我们如何自定义同步或者异步呢? 也是有两种方式
第一种方式: 自定义事件多波器,并指定taskExcutor
@Bean(name = applicationEventMulticaster)
ApplicationEventMulticaster simpleApplicationEventMulticaster() {
SimpleApplicationEventMulticaster eventMulticaster
= SimpleApplicationEventMulticaster();
ThreadPoolTaskExecutor
这里指定了 taskExecutor,就会使用异步的方式去执行
eventMulticaster.setTaskExecutor( SimpleAsyncTaskExecutor());
eventMulticaster;
}
第二种方式,在事件监听器上使用注解@Async
@Component
@Async
);
}
}
}
接下来看看如何广播事件的.?
*
* Invoke the given listener with the given event.
* @param listener the ApplicationListener to invoke
* @param event the current event to propagate
* @since 4.1
void invokeListener(ApplicationListener<?> listener,1)">) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != {
doInvokeListener(listener,event);
}
(Throwable err) {
errorHandler.handleError(err);
}
}
doInvokeListener(listener,1)">);
}
}
?
void doInvokeListener(ApplicationListener listener,1)"> ex;
}
}
}
其实,具体执行的逻辑,就是我们在监听器中定义的onApplicationEvent(event)方法中的逻辑实现.
?
三. 注册接口方式的监听器
在上面的源码分析中,注册接口方式的监听器,其实是由两个地方.?
第一个: 在第十步registerListener()
registerListeners() {
.....
*
* 第二步: 注册接口方式的监听器
* 获取beanDefinition中 ApplicationListener 类型的监听器.
* 也就是说,使用接口方式定义的监听器就可以在这里被注册到多播器的
* 这里是从BeanDefinition中拿的,那么就可以拿到. 因为它实现了ApplicationListener.
* 拿到了,就把监听器注册到多播器上.
* 如果是注解方式,那就拿不到了
*
把监听器注册到多播器上
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
.....
}
?另一个: 是在第三步进行属性填充的时候注册的
preparebeanfactory(ConfigurableListablebeanfactory beanfactory) {
......
*
* 注册事件监听器探测器后置处理器接口,ApplicationListenerDetector 解析接口方式的监听器
*/
beanfactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
......
}
在准备属性的方法里,有一个注册时间监听器探测器后置处理. 在这个监听器的探测器里面,进行了注册.
来看看ApplicationListenerDetector
ApplicationListenerDetector implements DestructionAwareBeanPostProcessor,MergedBeanDefinitionPostProcessor {
......*
* 初始化后的bean后置处理器
*
* 这个方法是在 registerListener 之后执行的,在registerListener()方法里注册过一次接口方式的监听器.
* 在这里还会在注册一次.
*
* 问题: 为什么同一个监听器,要在两个地方注册呢?
* 第一次添加的是监听器的名字,第二次添加的是bean实体. 那为什么要添加两次呢?
* 这是为了处理带有@Lazy懒加载方式的bean. 懒加载的bean是不会在初始化容器的时候创建bean的.
*
* 比如,我给监听器类加上一个@Lazy,那么他就不会走bean的后置处理器,因为bean的后置处理器,是在bean创建过程中调用的.
* 那什么时候会被调用呢? 在真正使用的时候. 比如调用 ctx.publishEvent(new OrderEvent(order,"减库存"));
* 马上就要用到了,所以,这时候回去调bean的后置处理器. 执行代码看一下效果
*
*
* @param bean the new bean instance
* @param beanName the name of the bean
* @return
(bean instanceof ApplicationListener) {
singleton bean (top-level or inner): register on the fly
'implements ApplicationListener interfacebut is not reachable for event multicasting by its containing ApplicationContextbecause it does not have singleton scope.Only top-level listener beans are allowed bean;
}
.......
}
我们看到在ApplicationListenerDetector中定义了方法postProcessAfterInitialization. 这个方法会在创建属性的第三步执行完以后调用. 第三步是初始化. 看名字也知道是初始化之后调用的后置处理器. 在这里,注册了接口类型的监听器
this.applicationContext.addApplicationListener((ApplicationListener<?>) bean);
那么,为什么要有两次注册呢?
其实这里是为了解决懒加载的问题. 因为,如果一个类是懒加载的类,那么他只有真正被调用的时候才回去加载. 所以,也就是在类进行初始化以后才会被调用. 因此在初始化之后再次加载了接口类型的监听器.?
四. 解析注解方式的监听器
整个流程走完,我们都只看到接口方式的监听器注册的地方. 那么注解类型的监听器是什么时候被创建的呢?
首先,注解是何时被解析的? 我们知道BeanDefinitionReader在解析创世纪的类的时候,注册了很多创世纪的类.其中就有两个是用于负责处理@EventListener注解的
再来回顾一下这段代码
static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry,@Nullable Object source) {
获取到beanfactory
DefaultListablebeanfactory beanfactory = unwrapDefaultListablebeanfactory(registry);
*
* 判断beanfactory中是否有AnnotationAwareOrderComparator和ContextAnnotationAutowireCandidateResolver
* 没有则添加
if (beanfactory != (beanfactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
beanfactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
(beanfactory.getAutowireCandidateResolver() instanceof
ContextAnnotationAutowireCandidateResolver)) {
beanfactory.setAutowireCandidateResolver( ContextAnnotationAutowireCandidateResolver());
}
}
BeanDefinitionHolder: 为BeanDefinition设置名字和别名
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8 如果registry中没有ConfigurationClassPostProcessor配置类后置处理器,就添加一个
registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.);
def.setSource(source);
构建BeanDefinitionHolder,并添加到beanDefs
beanDefs.add(registerPostProcessor(registry,def,CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
如果rigistry中,没有AutowiredAnnotationBeanPostProcessor Autowired注解bean的后置处理器,则添加一个
registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor. Check for JSR-250 support,and if present add the CommonAnnotationBeanPostProcessor.
检查对JSR-250的支持,如果rigistry中没有 CommonAnnotationBeanPostProcessor 通用注解后置处理器,1)">if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor. Check for JPA support,and if present add the PersistenceAnnotationBeanPostProcessor.
检查对jpa的支持,如果不包含 internalPersistenceAnnotationProcessor,持久化注解处理器,1)">if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = RootBeanDefinition();
{
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,AnnotationConfigUtils..getClassLoader()));
}
(ClassNotFoundException ex) {
IllegalStateException(
Cannot load optional framework class:
PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,ex);
}
def.setSource(source);
beanDefs.add(registerPostProcessor(registry,PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
}
/**
* 下面这两个注解是用来解析@EventListener的
*/
检查对事件监听的支持,如果不包含事件监听处理器 internalEventListenerProcessor,1)">
* EventListenerMethodProcessor : 既不是bean的后置处理器,也不是bean工厂的后置处理器
* 那么EventListenerMethodProcessor是在哪里被调用,并且解析注解方式的监听器呢?
*
* 下面看一下EventListenerMethodProcessor的继承结构图.
* 1. 实现了SmartInitializingSingleton接口 :
* 2. 实现了ApplicationContextAware接口 : 因为要往容器中注入bean,里面要使用容器的上下文,
* 将容器以Aware的方式set进来
* 3. 实现了beanfactoryPostProcessor接口 :
*
*
registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry,EVENT_LISTENER_PROCESSOR_BEAN_NAME));
}
如果不包含事件监听工厂处理器 internalEventListenerFactory,1)">EVENT_LISTENER_FACTORY_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory. beanDefs;
}

?如上图就是注册的创世纪的处理器. 最后两个就是用来处理@EventListener注解的.
下面来看看EventListenerMethodProcessor事件监听器处理器,
首先,?看一下EventListenerMethodProcessor的继承结构图.

?
?EventListenerMethodProcessor实现了三个接口.?
1.实现了SmartInitializingSingleton接口
2. 实现了ApplicationContextAware接口 : 因为要往容器中注入bean,将容器以Aware的方式set进来?
3. 实现了beanfactoryPostProcessor接口
SmartInitializingSingleton接口在哪里被用到了呢??
在refresh()#finishbeanfactoryInitialization(beanfactory); 实例化剩余的单例bean的过程中
在DefaultListablebeanfactory#preInstantiateSingletons()方法. 有两次循环遍历beanNames
preInstantiateSingletons() throws BeansException {
(logger.isTraceEnabled()) {
logger.trace(Pre-instantiating singletons in );
}
Iterate over a copy to allow for init methods which in turn register new bean definitions.
While this may not be part of the regular factory bootstrap,it does otherwise work fine.
获取容器中所有bean定义的名字
List<String> beanNames = new ArrayList<>(.beanDefinitionNames);
Trigger initialization of all non-lazy singleton beans...
/**
* 第一步: 循环bean定义的name,创建bean
*/
(String beanName : beanNames) {
获取bean定义
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
生产bean定义的条件: 不是抽象的,是单例的,不是懒加载的. 符合这个标准的,最后才会调用getBean()生产bean
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
这里判断是不是工厂bean,这里和beanfactory不是一个意思,判断当前这个bean是否实现了beanfactory的接口
(isfactorybean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
(bean instanceof factorybean) {
将bean转换为factorybean 工厂bean
final factorybean<?> factory = (factorybean<?>) bean;
boolean isEagerInit;
null && factory instanceof Smartfactorybean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((Smartfactorybean<?>) factory)::isEagerInit,getAccessControlContext());
}
{
isEagerInit = (factory instanceof Smartfactorybean &&
((Smartfactorybean<?>) factory).isEagerInit());
}
(isEagerInit) {
获取bean
getBean(beanName);
}
}
}
第二步: 调用getBean
getBean(beanName);
}
}
}
Trigger post-initialization callback for all applicable beans...
/**
* 第二步: 循环bean定义的name,解析是否有实现了SmartInitializingSingleton接口的类
* 到这里,bean都已经被创建完了
*/
从缓存中得到实例instance
Object singletonInstance = getSingleton(beanName);
(singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
;
},getAccessControlContext());
}
{
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
第一次循环,是创建bean,并获取bean
第二次循环,是在所有的bean都已经创建完以后,如果singletonInstance是SmartInitializingSingleton的实例,则调用afterSingletonsInstantiated()方法.?
以下是EventListenerMethodProcessor#afterSingletonsInstantiated()方法实现?
afterSingletonsInstantiated() {
从spring容器中获取EventListenerfactorybean
ConfigurableListablebeanfactory beanfactory = .beanfactory;
Assert.state(this.beanfactory != null,1)">No ConfigurableListablebeanfactory set 获取所有类型的bean
String[] beanNames = beanfactory.getBeanNamesForType(Object.ScopedProxyUtils.isScopedTarget(beanName)) {
Class<?> type = ;
{
type = AutoProxyUtils.determineTargetClass(beanfactory,beanName);
}
(Throwable ex) {
An unresolvable bean type,probably from a lazy bean - let's ignore it.
(logger.isDebugEnabled()) {
logger.debug(Could not resolve target class for bean with name ''if (type != ) {
if (ScopedObject..isAssignableFrom(type)) {
{
Class<?> targetClass = AutoProxyUtils.determineTargetClass(
beanfactory,ScopedProxyUtils.getTargetBeanName(beanName));
if (targetClass != ) {
type = targetClass;
}
}
(Throwable ex) {
An invalid scoped proxy arrangement - let's ignore it.
(logger.isDebugEnabled()) {
logger.debug(Could not resolve target bean for scoped proxy '" +
beanName + {
processBean(beanName,type);
}
(Throwable ex) {
new BeanInitializationException(Failed to process @EventListener " +
annotation on bean with name 'void processBean(final String beanName,final Class<?> targetType) {
// 1. 是否包含注解@EventListener
this.nonAnnotatedClasses.contains(targetType) &&
AnnotationUtils.isCandidateClass(targetType,EventListener.class) &&
!isSpringContainerClass(targetType)) {
Map<Method,EventListener> annotatedMethods = ;
// 2. 查找@EventListener注解,如果有则拿到标注@EventListener的方法
annotatedMethods = MethodIntrospector.selectMethods(targetType,(MethodIntrospector.MetadataLookup<EventListener>) method ->
AnnotatedElementUtils.findMergedAnnotation(method,1)"> (Throwable ex) {
An unresolvable type in a method signature,probably from a lazy bean - let's ignore it.
(logger.isDebugEnabled()) {
logger.debug(Could not resolve methods for bean with name ' (CollectionUtils.isEmpty(annotatedMethods)) {
.nonAnnotatedClasses.add(targetType);
No @EventListener annotations found on bean class: targetType.getName());
}
}
Non-empty set of methods
ConfigurableApplicationContext context = .applicationContext;
Assert.state(context != No ApplicationContext set);
// 3. 获取bean工厂. 这个bean工厂是我们在创世纪的时候注册的EventListenerFactory
List<EventListenerFactory> factories = .eventListenerFactories;
Assert.state(factories != EventListenerFactory List not initialized);
// 4. 循环遍历有注解的方法
(Method method : annotatedMethods.keySet()) {
(EventListenerFactory factory : factories) {
(factory.supportsMethod(method)) {
Method methodToUse = AopUtils.selectInvocableMethod(method,context.getType(beanName));
//5. 创建事件监听器
ApplicationListener<?> applicationListener =
factory.createApplicationListener(beanName,targetType,methodToUse);
(applicationListener instanceof ApplicationListenerMethodAdapter) {
((ApplicationListenerMethodAdapter) applicationListener).
init(context,1)">.evaluator);
}
// 6. 将监听器注入到多播器中
context.addApplicationListener(applicationListener);
break;
}
}
}
(logger.isDebugEnabled()) {
logger.debug(annotatedMethods.size() + @EventListener methods processed on bean '
beanName + ': annotatedMethods);
}
}
}
}
1. 首先判断,是否包含@EventListener注解
2.?查找@EventListener注解,如果有则拿到标注@EventListener的方法
3.?获取bean工厂. 这个bean工厂是我们在创世纪的时候注册的EventListenerFactory
4. 循环遍历有注解的方法
5. 创建事件监听器
6. 将监听器注入到多播器中
?
?以上就是注解版的监听器是如何注入到多播器中的.?
五. 怎样在所有的bean都创建完以后做扩展代码?
第一种方式,添加内置的监听器,类加载完以后,调用监听器
第二种方法. 就是在使用注解方式的时候,??实现SmartInitializingSingleton接口. 然后在bean实例化完成以后,在调用
?
(编辑:北几岛)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!