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 ...
随机推荐
- 【Flutter】如何优美地实现一个悬浮NavigationBar
[Flutter]如何优美地实现一个悬浮NavigationBar 最近写代码的时候遇到了一个如下的需求: 整体来说,底部的条是一个浮动的悬浮窗,有如下的三个按钮: 点击左边的要进入"主页& ...
- Flask框架——flask介绍
文章目录 1 什么是flask? 2 为什么要有flask? 3 学前准备:虚拟环境 3.1 虚拟环境是什么? 3.2 如何使用虚拟环境? 3.2.1 搭建虚拟环境 3.2.1 在虚拟环境中安装我们的 ...
- 教育法学期末考试02MOOC
期末考试 返回 期末考试试卷为客观题,总分为100分,占课程成绩的40%.其中包含16道单选题,2道多选题.共18道题.单选题每道5分,多选题每道10分,限时90分钟完成. 倒计时: 01:21: ...
- torch.nn.ReLU(inplace=True)的具体含义:
首先根据源文档中的ReLU(x)=max(0,x),得出结论.大于0的数值不变,小于0的数据变成0. 补充:这里需要注意的是 ReLU并没有限制数据的大小. 这是对应的文档链接:https://pyt ...
- Oracle 高可用 阅读笔记
1 个人理解概述 1.1 Oracle dg Oracle Data Guard通过从主数据库传输redo data,然后将apply redo到备用数据库,自动维护每个备用数据库.DG分为3个 ...
- 【pwn】[SWPUCTF 2022 新生赛]InfoPrinter--格式化字符串漏洞,got表劫持,data段修改
下载附件,checksec检查程序保护情况: No RELRO,说明got表可修改 接下来看主程序: 函数逻辑还是比较简单,14行出现格式化字符串漏洞,配合pwntools的fmtstr_payloa ...
- 《最新出炉》系列初窥篇-Python+Playwright自动化测试-27-处理单选和多选按钮-番外篇
1.简介 前边几篇文章是宏哥自己在本地弄了一个单选和多选的demo,然后又找了网上相关联的例子给小伙伴或童鞋们演示了一下如何使用playwright来处理单选按钮和多选按钮进行自动化测试,想必大家都已 ...
- Codeforces Round #538 (Div. 2) F. Please, another Queries on Array?
原题链接 F. Please, another Queries on Array? 这道题让求\(\phi(\prod\limits_{i = l}^r a_i)\),然后我们化简一下. 设\(P\) ...
- Cadence SPB 22.1 -- 元件库的创建02Day
一.原理图元件库工程 (1).新建工程:执行菜单命令"File"→"New"→"Project",输入工程名字.存储位置等基本信息保存即可: ...
- VM离线安装Centos 8以及配置
一.安装 1.预装准备 1.1. 硬件准备 物理内存:2G以上(这里指系统搭建所需占用空间) 物理外存:20G(这里指系统搭建所需占用空间) 1.2. 环境搭建准备 Window10系统电脑一台.Vm ...