Spring5源码 - 13 Spring事件监听机制_@EventListener源码解析
文章目录
- Pre
- 概览
- 开天辟地的时候初始化的处理器
- @EventListener
- EventListenerMethodProcessor
- afterSingletonsInstantiated
- 小结
- 发布事件
- 附 <异步派发和异常处理器>
Pre
Spring5源码 - 10 Spring事件监听机制_应用篇
Spring5源码 - 11 Spring事件监听机制_源码篇
Spring5源码 - 12 Spring事件监听机制_异步事件监听应用及源码解析
通过上面三篇文章的学习,是不是发现没有看到Spring是如何解析@EventListener注解的呢? Let’s go ~~~
概览
Spring容器在启动的时候初始化EventListenerMethodProcessor和DefaultEventListenerFactory,用于处理@EventListener注解, 调用EventListenerMethodProcessor的afterSingletonsInstantiated方法。
开天辟地的时候初始化的处理器
/*** 处理监听方法的注解解析器EventListenerMethodProcessor*/if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));}/*** 注册事件监听器工厂*/if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);def.setSource(source);beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));}
一个是注册一个用于解析@EventListener注解的EventListenerMethodProcessor ,一个是注册事件监听工厂。
@EventListener
EventListenerMethodProcessor
我们来看下EventListenerMethodProcessor的类继承结构
EventListenerMethodProcessor 实现了 EventListenerMethodProcessor,所以执行 BeanFactory 后置处理器时,会调用 postProcessBeanFactory(),将 DefaultEventListenerFactory 添加到缓存中。
可以看到EventListenerMethodProcessor实现了SmartInitializingSingleton接口 , 那肯定要重写 afterSingletonsInstantiated方法。
我们知道SmartInitializingSingleton接口是在所有的Bean实例化完成以后,Spring回调的方法。 获取所有的 BeanFactory,找到其中标注了 @EventListener 的方法,利用反射和 DefaultEventListenerFactory 为其创建 ApplicationListener,并添加到事件派发器的缓存中。
refresh----> finishBeanFactoryInitialization(beanFactory);---->preInstantiateSingletons()
afterSingletonsInstantiated
我们看下 EventListenerMethodProcessor的afterSingletonsInstantiated方法
@Overridepublic void afterSingletonsInstantiated() {//从BeanFactory中获取EventListenerFactory,EventListenerFactory共有2个实现,一个是DefaultEventListenerFactory,对普通的@EventListener进行解析,另一个是TransactionalEventListenerFactory,可以对@TransactionalEventListener进行解析。List<EventListenerFactory> factories = getEventListenerFactories();ConfigurableApplicationContext context = getApplicationContext();// 获取所有的beanNamesString[] beanNames = context.getBeanNamesForType(Object.class);// 遍历循环for (String beanName : beanNames) {........// 关键:处理bean processBean(factories, beanName, type);.........}}}
protected void processBean(final List<EventListenerFactory> factories, final String beanName, final Class<?> targetType) {if (!this.nonAnnotatedClasses.contains(targetType)) {Map<Method, EventListener> annotatedMethods = null;try {//查找带@EventListener注解的方法annotatedMethods = MethodIntrospector.selectMethods(targetType,new MethodIntrospector.MetadataLookup<EventListener>() {@Overridepublic EventListener inspect(Method method) {return AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class);}});}catch (Throwable ex) {.......}//如果没有找到带EventListener注解的方法if (CollectionUtils.isEmpty(annotatedMethods)) {this.nonAnnotatedClasses.add(targetType);........}//否则else {// Non-empty set of methods//遍历for (Method method : annotatedMethods.keySet()) {for (EventListenerFactory factory : factories) {//EventListenerFactory是否支持对该method的处理if (factory.supportsMethod(method)) {Method methodToUse = AopUtils.selectInvocableMethod(method, this.applicationContext.getType(beanName));// 创建事件监听器ApplicationListener<?> applicationListener =factory.createApplicationListener(beanName, targetType, methodToUse); if (applicationListener instanceof ApplicationListenerMethodAdapter) {((ApplicationListenerMethodAdapter) applicationListener).init(this.applicationContext, this.evaluator);}// 注册事件到Context中this.applicationContext.addApplicationListener(applicationListener);break;}}}.......}}}
小结
processBean的主要业务逻辑:
- 查找带@EventListener注解的方法 、
- 不为空的话,遍历找到的方法
- 在遍历方法的循环中,遍历EventListenerFactory,如果支持,实例化
ApplicationListenerMethodAdapter
- 初始化完成后, 向application中注册applicationListener
发布事件
基于@EventListener注解的,发布事件流程和基于接口的一样,唯一的区别在于
跟进去走到 listener.onApplicationEvent(event) ,基于注解的会走到 ApplicationListenerMethodAdapter实现类中 onApplicationEvent方法,基于注解的是反射调用,而基于接口的形式是直接调用实现类的onApplicationEvent
onApplicationEvent调用了processEvent
反射调用
基于接口,可以参考我的前面的博客: Spring5源码 - 10 Spring事件监听机制_应用篇
附 <异步派发和异常处理器>
- 如果事件派发器设置了 Executor,则异步多线程的事件派发
- 如果事件派发器设置了 ErrorHandler,则用异常处理器来处理异常
Spring5源码 - 13 Spring事件监听机制_@EventListener源码解析相关推荐
- Spring5源码 - 12 Spring事件监听机制_异步事件监听应用及源码解析
文章目录 Pre 实现原理 应用 配置类 Event事件 事件监听 EventListener 发布事件 publishEvent 源码解析 (反推) Spring默认的事件广播器 SimpleApp ...
- Spring5源码 - 11 Spring事件监听机制_源码篇
文章目录 pre 事件监听机制的实现原理[观察者模式] 事件 ApplicationEvent 事件监听者 ApplicationEvent 事件发布者 ApplicationEventMultica ...
- Spring5源码 - 10 Spring事件监听机制_应用篇
文章目录 Spring事件概览 事件 自定义事件 事件监听器 基于接口 基于注解 事件广播器 Spring事件概览 Spring事件体系包括三个组件:事件,事件监听器,事件广播器 事件 Spring的 ...
- Spring事件监听流程分析【源码浅析】
一.简介 Spring早期是通过实现ApplicationListener接口来定义监听事件,在spring4.2的时候开始我们可以通过@EventListener注解来定义监听事件,Applicat ...
- spring 扫描所有_自定义Spring事件监听机制
开头提醒一下大家: 尽管我简化了Spring源码搞了个精简版的Spring事件机制,但是没接触过Spring源码的朋友阅读起来还是有很大难度,请复制代码到本地,边Debug边看 既然要简化代码,所以不 ...
- Springboot事件监听机制:工作原理
目录 前言 1.观察者模式 1.1观察者模式的核心元素 1.2观察者模式的工作流程 2.springboot事件监听机制的基本工作原理 2.1事件发布器是什么时候在哪里产生的呢? 2.2事件监听器是什 ...
- Spring容器的事件监听机制(简单明了的介绍)
文章目录 前言 事件 1. 定义事件 2. 定义监听器 3. 定义发布器 Spring容器的事件监听机制 1.事件的继承类图 监听器的继承类图 总结 前言 上一篇我们介绍了SpringFactorie ...
- spring 事件监听
用一个简单的例子来实现spring事件监听的功能 这个例子主要功能是,记录那些用户是第一次登入系统,如果用户是第一次登入系统,则调用spring的事件监听,记录这些用户. 主要用到的spring的类和 ...
- spring中的事件监听机制
Spring event listener 介绍 example 简单原理解释 自定义事件.监听和发布 事件 监听器 发布者 测试 更加一般的事件 @EventListener原理 介绍 exampl ...
最新文章
- 帝国cms商城微信小程序之后台sku多规格的开发说明
- 使用Linux auto Makefile自动生成的运行步骤
- 回望之六:太阳山与红寺堡
- .NET Core:通过Web API进行微服务交互
- 【ASP.NET Web API教程】2.3.4 创建Admin视图
- java安装包_Java6 Update
- Unity-粒子特效
- Linux系统内核升级
- Java前景如何,容易找工作嘛
- 输入一个数,打印一个三角形
- c语言小饭店等位就餐程序,小饭店预约登记管理系统,
- csf格式转换--逼自己一把
- 指纹识别系统电路设计图集锦 —电路图天天读(200)
- Python正则表达式及match函数的用法
- 《动物世界》电影 观后感
- 洞见趋势系列(二)特征工程
- 深度学习,提高分类精度
- 集赞免费领《新程序员》电子刊!
- 微信公众号发送客服消息(文本、图文)和模板消息
- Android 必须知道2018年流行的框架库及开发语言,看这一篇就够了!
热门文章
- 5获取按钮返回值消息_大数据从入门到深入:JavaEE 之 项目实战 项目基础编码阶段(5)...
- cmake之 ADD_LIBRARY()
- ttlink无线打印服务器固件,TTLINK TT-180U1打印机服务器 TCP/IP添加打印机的教程
- vue 只在父级容器移动_Vue易遗忘的基础复习(二)
- 点云网络的论文理解(四)-点云网络的优化 PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space
- 推荐系统笔记:决策树回归树
- 深度学习核心技术精讲100篇(一)-数据分析中有哪些分析指标?
- python之获取目录下的文件名
- 这个程序,有点意思!
- 获取列表中最大N个数的索引