文章目录

  • 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的主要业务逻辑:

  1. 查找带@EventListener注解的方法 、
  2. 不为空的话,遍历找到的方法
  3. 在遍历方法的循环中,遍历EventListenerFactory,如果支持,实例化ApplicationListenerMethodAdapter
  4. 初始化完成后, 向application中注册applicationListener

发布事件

基于@EventListener注解的,发布事件流程和基于接口的一样,唯一的区别在于

跟进去走到 listener.onApplicationEvent(event) ,基于注解的会走到 ApplicationListenerMethodAdapter实现类中 onApplicationEvent方法,基于注解的是反射调用,而基于接口的形式是直接调用实现类的onApplicationEvent

onApplicationEvent调用了processEvent

反射调用

基于接口,可以参考我的前面的博客: Spring5源码 - 10 Spring事件监听机制_应用篇


附 <异步派发和异常处理器>

  • 如果事件派发器设置了 Executor,则异步多线程的事件派发
  • 如果事件派发器设置了 ErrorHandler,则用异常处理器来处理异常

Spring5源码 - 13 Spring事件监听机制_@EventListener源码解析相关推荐

  1. Spring5源码 - 12 Spring事件监听机制_异步事件监听应用及源码解析

    文章目录 Pre 实现原理 应用 配置类 Event事件 事件监听 EventListener 发布事件 publishEvent 源码解析 (反推) Spring默认的事件广播器 SimpleApp ...

  2. Spring5源码 - 11 Spring事件监听机制_源码篇

    文章目录 pre 事件监听机制的实现原理[观察者模式] 事件 ApplicationEvent 事件监听者 ApplicationEvent 事件发布者 ApplicationEventMultica ...

  3. Spring5源码 - 10 Spring事件监听机制_应用篇

    文章目录 Spring事件概览 事件 自定义事件 事件监听器 基于接口 基于注解 事件广播器 Spring事件概览 Spring事件体系包括三个组件:事件,事件监听器,事件广播器 事件 Spring的 ...

  4. Spring事件监听流程分析【源码浅析】

    一.简介 Spring早期是通过实现ApplicationListener接口来定义监听事件,在spring4.2的时候开始我们可以通过@EventListener注解来定义监听事件,Applicat ...

  5. spring 扫描所有_自定义Spring事件监听机制

    开头提醒一下大家: 尽管我简化了Spring源码搞了个精简版的Spring事件机制,但是没接触过Spring源码的朋友阅读起来还是有很大难度,请复制代码到本地,边Debug边看 既然要简化代码,所以不 ...

  6. Springboot事件监听机制:工作原理

    目录 前言 1.观察者模式 1.1观察者模式的核心元素 1.2观察者模式的工作流程 2.springboot事件监听机制的基本工作原理 2.1事件发布器是什么时候在哪里产生的呢? 2.2事件监听器是什 ...

  7. Spring容器的事件监听机制(简单明了的介绍)

    文章目录 前言 事件 1. 定义事件 2. 定义监听器 3. 定义发布器 Spring容器的事件监听机制 1.事件的继承类图 监听器的继承类图 总结 前言 上一篇我们介绍了SpringFactorie ...

  8. spring 事件监听

    用一个简单的例子来实现spring事件监听的功能 这个例子主要功能是,记录那些用户是第一次登入系统,如果用户是第一次登入系统,则调用spring的事件监听,记录这些用户. 主要用到的spring的类和 ...

  9. spring中的事件监听机制

    Spring event listener 介绍 example 简单原理解释 自定义事件.监听和发布 事件 监听器 发布者 测试 更加一般的事件 @EventListener原理 介绍 exampl ...

最新文章

  1. 帝国cms商城微信小程序之后台sku多规格的开发说明
  2. 使用Linux auto Makefile自动生成的运行步骤
  3. 回望之六:太阳山与红寺堡
  4. .NET Core:通过Web API进行微服务交互
  5. 【ASP.NET Web API教程】2.3.4 创建Admin视图
  6. java安装包_Java6 Update
  7. Unity-粒子特效
  8. Linux系统内核升级
  9. Java前景如何,容易找工作嘛
  10. 输入一个数,打印一个三角形
  11. c语言小饭店等位就餐程序,小饭店预约登记管理系统,
  12. csf格式转换--逼自己一把
  13. 指纹识别系统电路设计图集锦 —电路图天天读(200)
  14. Python正则表达式及match函数的用法
  15. 《动物世界》电影 观后感
  16. 洞见趋势系列(二)特征工程
  17. 深度学习,提高分类精度
  18. 集赞免费领《新程序员》电子刊!
  19. 微信公众号发送客服消息(文本、图文)和模板消息
  20. Android 必须知道2018年流行的框架库及开发语言,看这一篇就够了!

热门文章

  1. 5获取按钮返回值消息_大数据从入门到深入:JavaEE 之 项目实战 项目基础编码阶段(5)...
  2. cmake之 ADD_LIBRARY()
  3. ttlink无线打印服务器固件,TTLINK TT-180U1打印机服务器 TCP/IP添加打印机的教程
  4. vue 只在父级容器移动_Vue易遗忘的基础复习(二)
  5. 点云网络的论文理解(四)-点云网络的优化 PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space
  6. 推荐系统笔记:决策树回归树
  7. 深度学习核心技术精讲100篇(一)-数据分析中有哪些分析指标?
  8. python之获取目录下的文件名
  9. 这个程序,有点意思!
  10. 获取列表中最大N个数的索引