spring源码分析-ApplicationContext----扩展组件event listener

        我们知道 spring中的ApplicationContext在beanFactory(提供基础bean处理)基础上增加了扩展组件,例如国际化,资源,发布事件和监听事件,今天主要针对发布和监听事件做一次源码分析,看到底发布和监听是如何实现的?是否放队列消费 还是直接调用?

        核心代码如下

SimpleApplicationEventMulticaster中的multicastEvent方法 广播事件,从对应监听器set集合中遍历,取出对应监听器并直接调用监听器中的方法,整个大的过程包括

1.先实例化监听器并放到set集合中,

2.将发布事件存入到set集合中,

3.在spring调用refresh方法之后进行调用广播事件方法,其实是直接调用的监听器中的对应方法。

AbstractApplicationContext的注册监听器方法 将标注为@EventListener的类添加到set集合中。

调用步骤在spring加载bean的refresh方法之后,如下图

 

         可以看到循环是从getApplicationListeners()方法中获取的set集合,那这个集合又是哪里存的呢?点开getApplicationListeners()方法后的set集合 继续点击发现是如下方法存的值

 而这个方法又是在如下步骤被调用的,从refresh之后调用监听可以得知 这个set过程一定是在此之前的,可以详细看下这里的入口又是哪里。

这个方法在一开始先查找需要进行AOP处理的类名称和类类型,且类类型是实现了EventListener的。

之后拿到这些标注了EventListener注解的类进行调用以上处理监听具体内容的方法。这里重点要看

AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));

这个方法 是查询方法上标注了注解为EventListener.class的类,找到了注解所标注的类,就可以知道哪些监听器需要处理,然后调用监听器处理方法时,只需要将set集合中保存的事件内容传递即可(监听方法入参)。

是实例化的时候调用的 那么这类的实例化又是哪里调用的?请看bean加载的生命周期,如下

a、创建一个beanDefinitionNames的副本,用于后面循环初始化bean对象;

b、循环前一步骤的beanNames副本,挨个触发非懒加载、单例bean的初始化;

c、首先初始化的前提是bean不是抽象类、非懒加载的、并且是单例的;接着会判断bean是否实现了FactoryBean接口,如果bean实现了FactoryBean接口,那么通过getBean(&beanName)获取的是FactoryBean对象本身。再然后判断bean是否急切需要初始化,如果需要急切初始化,则会直接调用getBean方法初始化;

d、如果没有实现FactoryBean接口的bean,则执行普通的getBean逻辑;

e、最后,如果bean实例singletonInstance实现了SmartInitializingSingleton接口,则执行后初始化回调方法afterSingletonsInstantiated();

重点在最后的bean实例执行完初始化(变量赋值完成)之后进行回调。这里要注意是所有的加载到spring容器中的bean都会调用 不过上面的分析中会查看哪个类的方法包含EventListener注解,所以相当于执行回调的过程中检查了对应注解 进行处理。

整体流程就是如此

主要分为两块

1.在类初始化完成后回调过程中 去发现方法中标注了EventListener注解的类,找到之后放到set集合中。

2.在refresh方法调用完之后调用监听器的处理时,从刚才的set集合中取出监听器进行处理,处理过程中当然也需要拿出event进行传递,event对象在发布事件的时候已经存到一个set集合中。

分析的略有些杂乱,但是顺着代码看就会感觉很简单,大家批评指教!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值