Spring源码学习笔记5——注册BeanPostProcessor,初始化事件多播器,注册事件监听器
一丶前言
上篇Spring容器回调完所有的BeanFactoryPostPocessor,之后可以做到替换所有占位符,解析所有配置类等工作,这篇还会迎来一个Spring留给我们扩展的一个接口,涉及到Aop的实现
二丶注册BeanPostProcessor后置处理器
1.什么是BeanPostProcessor
一个允许自定义修改新 bean 实例的工厂接口,作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的
和上篇的 BeanFactoryPostProcessor 名称很像,但是BeanFactoryPostProcessor是针对整个BeanFactory 进行操作,允许我们修改BeanDefinition,注册我们自己的BeanDefinition等,针对一个Bean使用BeanPostProcessor更好,可以为这个Bean生成一个代理
public interface BeanPostProcessor {
// bean实例化但属性没有填充时回调
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
// bean 依赖注入,属性填充后调用
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
2.注册BeanPostProcessor

处理流程也比较简单,获取BeanFactory中的BeanPostProcessor类型的bean,对于实现PriorityOrdered的BeanPostProcessor,排序并优先放入BeanPostProcessor集合中(通常是一个CopyOnWriteList)先放意味着会先执行,对于实现Ordered的BeanPostProcessor,排序再放入,没有实现Ordered or PriorityOrdered的BeanPostProcessor,不会排序,直接放入(注意这说明BeanPostProcessor的顺序不会受到@Order注解的影响,可能是觉得BeanPostProcessor肯定是需要编写一个类实现接口的,那么继承以下Ordered 和PriorityOrdered吧 )最后对于实现了MergedBeanDefinitionPostProcessor的BeanPostProcessor进行放入,最后把ApplicationListenerDetector放在末尾(笔记三说过这个类,主要是在监听器类型的bean被销毁的时候,会从事件多播器中移除)
3.MergedBeanDefinitionPostProcessor

MergedBeanDefinitionPostProcessor 的调用是在创建完 bean 实例之后,在 Bean属性填充 之前,将调用 MergedBeanDefinitionPostProcessor 的 postProcessMergedBeanDefinition 方法。
3.1 CommonAnnotationBeanPostProcessor
解析类中的@Resource,@PostConstruct,@PreDestroy,并且正确的时机执行


其中这个类还实现了 InstantiationAwareBeanPostProcessor,在Bean设置属性的时候,获取@Resouce注解并且进行依赖注入
3.2 AutowiredAnnotationBeanPostProcessor
解析@Autowrie,和@Value注解,在依赖注入的时候发会作用
还要很多和Bean生命周期相关的接口,贯穿bean的生命周期,这个后续Bean生命周期学习中进行总结
三丶初始化事件多播器

1.AbstractApplicationContext推送事件

注意当前容器执行之后还会调用父容器中的监听器响应
2.SimpleApplicationEventMulticaster
事件多播器的简单实现
2.1 推送事件


四丶注册事件监听器

负责把事件监听器 注册到多播器中,并且在事件多播器初始化执行之前,可能存在一些事件没有处理,这些事件都会放在earlyApplicationEvents集合中,在多播器初始化后,会把earlyApplicationEvents置为null 以后的事件都是直接委托给多播器进行推送
1.对于@EventLister的方法是怎么注册
这种类型的方法被封装成了ApplicationLister,也是在注册事件监听器会注册到多播器中,注册到多播器,存在一个类——EventListenerMethodProcessor负责处理这些方法,在调用所有BeanFactoryPostProcessor的时候会调用到
EventListenerMethodProcessor
1.1类结构图

- SmartInitializingSingleton 具有方法 afterSingletonsInstantiated 在bean初始化后会被容器回调使用
1.2 初始化解析Method 生成ApplicationLister的策略
EventListenerMethodProcessor的 postProcessBeanFactory方法

public interface EventListenerFactory {
//是否可以把当前方法包装成一个 ApplicationListener
boolean supportsMethod(Method method);
// 当前bean的名称 和 标注事件监听注解的方法 生成一个ApplicationListener
ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method);
}

具有两个实现,这EventListenerMethodProcessor使用策略模式,调用者两个类,把符合要求的方法封装成ApplicationLister对象,注册到上下文(上下文会把它们注册到多播器)
1.3把标有@EventLister注册的方法封装成ApplicationListener
在afterSingletonsInstantiated方法中实现,在bean初始化后会被容器回调使用,获取容器中所有的bean,调用processBean方法把其中标注@EventListener的方法,or @EventListener符合注册的方法,包装一个ApplicationListener 并且注册到上下文中
1.3.1获取具有@EventLister注解的方法

1.3.2 使用对应的策略生成ApplicationListner
超级经典的 策略+工厂+责任链设计模式,妙呀
2.DefaultEventListenerFactory&ApplicationListenerMethodAdapter

默认的策略,直接new 一个ApplicationListenerMethodAdapter

2.1 ApplicationListenerMethodAdapter构造方法
这里的order 来自@Order注解 如果没有注解那么默认最低优先级,这里的condition
2.2 处理事件

解析参数

反射执行

返回值处理

我们可以返回CompletionStage<事件,异常>会继续推送事件
如果返回的是ListenableFuture(继承了Future)在执行完后进行回调——继续推送事件
3.TransactionalEventListenerFactory&TransactionalApplicationListenerMethodAdapter


TransactionSynchronizationManager 这个类有点复杂后续详细学习
如果事务处于活跃状态


Spring源码学习笔记5——注册BeanPostProcessor,初始化事件多播器,注册事件监听器的更多相关文章
- Spring 源码学习笔记11——Spring事务
Spring 源码学习笔记11--Spring事务 Spring事务是基于Spring Aop的扩展 AOP的知识参见<Spring 源码学习笔记10--Spring AOP> 图片参考了 ...
- Spring源码学习笔记12——总结篇,IOC,Bean的生命周期,三大扩展点
Spring源码学习笔记12--总结篇,IOC,Bean的生命周期,三大扩展点 参考了Spring 官网文档 https://docs.spring.io/spring-framework/docs/ ...
- Spring 源码学习笔记10——Spring AOP
Spring 源码学习笔记10--Spring AOP 参考书籍<Spring技术内幕>Spring AOP的实现章节 书有点老,但是里面一些概念还是总结比较到位 源码基于Spring-a ...
- Spring源码学习笔记9——构造器注入及其循环依赖
Spring源码学习笔记9--构造器注入及其循环依赖 一丶前言 前面我们分析了spring基于字段的和基于set方法注入的原理,但是没有分析第二常用的注入方式(构造器注入)(第一常用字段注入),并且在 ...
- spring源码学习笔记之容器的基本实现(一)
前言 最近学习了<<Spring源码深度解析>>受益匪浅,本博客是对学习内容的一个总结.分享,方便日后自己复习或与一同学习的小伙伴一起探讨之用. 建议与源码配合使用,效果更嘉, ...
- Spring源码学习笔记之基于ClassPathXmlApplicationContext进行bean标签解析
bean 标签在spring的配置文件中, 是非常重要的一个标签, 即便现在boot项目比较流行, 但是还是有必要理解bean标签的解析流程,有助于我们进行 基于注解配置, 也知道各个标签的作用,以及 ...
- Spring源码学习笔记之bean标签属性介绍及作用
传统的Spring项目, xml 配置bean在代码中是经常遇到, 那么在配置bean的时候,这些属性的作用是什么呢? 虽然说现在boot项目兴起,基于xml配置的少了很多, 但是如果能够了解这些标签 ...
- Spring源码学习笔记2
1.默认标签的解析 对四种不同标签的解析 private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate dele ...
- vue 2.0源码学习笔记—new Vue ( Vue 初始化过程 )
new Vue(Vue 初始化) 一个vue实例化到底经历了什么?已下是博主自己的总结,不正确的地方请指出,谢谢~ 一.简述 从使用角度来看,挂载的顺序如下 1. $slots 2. $scopedS ...
- Spring源码学习笔记1
1.Spring中最核心的两个类 1)DefaultListableBeanFactory XmlBeanFactory继承自DefaultListableBeanFactory,DefaultLis ...
随机推荐
- 背景图片随机API
在美化博客园的时候,遇到了一个问题:博客背景图片只支持一张图片,看到有道友说可以用API随机图片. 于是就有了这篇文章. 本文主要整理了一些随机图片API,希望对你有帮助. 岁月小筑 https:// ...
- PostgreSQL学习笔记-7.基础知识:子查询、自增、PRIVILEGES 权限
子查询 子查询或称为内部查询.嵌套查询,指的是在 PostgreSQL 查询中的 WHERE 子句中嵌入查询语句.一个 SELECT 语句的查询结果能够作为另一个语句的输入值.子查询可以与 SELEC ...
- About Info-ZIP
LATEST RELEASES: Zip 3.00 was released on 7 July 2008. WiZ 5.03 was released on 11 March 2005. UnZip ...
- C#/.NET/.NET Core优秀项目和框架精选(2023年10月更新,项目分类已整理完成欢迎大家踊跃提交PR一起完善让优秀的项目和框架不被埋没)
前言 帮助开发者发现功能强大.性能优越.创新前沿.简单易用的C#/.NET/.NET Core优秀项目和框架,无论你是寻找灵感.学习新技术.改进代码质量,还是想拓展自己的技术视野,都能为你提供有价值的 ...
- 如何在linux系统中安装python3.8.1 并卸载 python3.6.2 更新python3引导到3.8.1
安装python3.8.1 步骤 1:检查Python版本 在终端中输入以下命令来检查当前安装的Python版本: python --version 步骤 2:安装编译Python所需的依赖项 更新系 ...
- 我们在开发第一个flutter小程序时需要注意什么
Flutter这些年发展的很快,特别是在 Google 持续的加持下,Flutter SDK 的版本号已经来到了 3开头,也正式开始对 Windows.macOS 和 Linux 桌面环境提供支持.如 ...
- 五分钟k8s实战-Istio 网关
在上一期 k8s-服务网格实战-配置 Mesh 中讲解了如何配置集群内的 Mesh 请求,Istio 同样也可以处理集群外部流量,也就是我们常见的网关. 其实和之前讲到的k8s入门到实战-使用Ingr ...
- 轻松一刻|Walrus CLI与CI/CD工具集成,轻松部署2048游戏
Walrus 是一款开源的基于平台工程理念.以应用为中心.以完整应用系统自动化编排交付为目标进行设计开发的云原生应用平台,简化和自动化应用部署与发布流程并与现有的 CI/CD 流水线无缝集成.今天我们 ...
- 哈希表(hash)
散列表(Hash table,也叫哈希表),是根据键(Key)而直接访问在内存储存位置的数据结构.也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度 ...
- 在路上---学习篇(一)Python 数据结构和算法 (2) -- 冒泡排序、选择排序、插入排序
独白: 第一次接触算法排序, 充满了好奇并且渴望了解其中原理,今天先学习了三种排序的方法,分别是 冒泡排序.选择排序.插入排序.学完以后发现数学知识真的很重要,越牛逼的算法要求知识越多,越精.虽说刚接 ...