Spring的BeanPostProcessor后置处理器与bean的生命周期
前言
本文将把Spring在Bean的生命周期中涉及到的后置处理器一一梳理出来,并简要说一下功能,至于每个后置处理器在实际扩展中的用处,还要后续慢慢探索总结。
正文
下面一步步跟进探寻那些后置处理器们。首先进入AbstractApplicationContext类中的refresh方法,继续追踪至此模板方法中的finishBeanFactoryInitialization方法,然后点进beanFactory.preInstantiateSingletons()方法,进入DefaultListableBeanFactory类中,点进getBean方法,继续点击doGetBean方法,它是获取bean的核心方法,但我们只关注里面lambda表达式中的createBean方法,点之进入AbstractAutowireCapableBeanFactory#createBean方法,逐渐逼近无知兽。
第一处
在createBean方法的resolveBeforeInstantiation方法中,遇见第一处后置处理器的调用,而且一次调了两种,分别是:InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation和
BeanPostProcessor.postProcessAfterInitialization。如下截图所示:

此处如果before的方法返回的bean不为null, 方法返回之后在createBean方法中就不会往下走了(即后续的2-8处理器都不走)而是直接返回。
额外说一下Spring的使用实例。如果bean中有切面类,那么会调用AbstractAutoProxyCreator#postProcessBeforeInstantiation中的实现逻辑,在此方法中将切面类加入advisedBeans中,这样后续切面会自动忽略对advisedBeans中对象的拦截。
第二处
进入createBean中的doCreateBean方法,在createBeanInstance方法中调用了determineConstructorsFromBeanPostProcessors方法,里面是第二处后置处理器的调用:SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors。截图如下所示,此处后置处理器用于推断构造方法,默认调用的实现类是AutowiredAnnotationBeanPostProcessor。

第三处
回到doCreateBean方法,继续往下看applyMergedBeanDefinitionPostProcessors方法,找到第三处后置处理器的调用:MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition。截图如下所示:

第四处
在doCreateBean中继续往下找,getEarlyBeanReference方法中找到第四处调用:SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference。此处用于解决循环依赖,截图如下:

第五处
继续往下,进入populateBean方法,在此方法中有两处调用,第五处:InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation。返回布尔类型,用于判断是不是需要属性填充,如果返回false则直接从populateBean中返回,不再执行第6/7/8处。

第六处
第六处调用了两个方法:InstantiationAwareBeanPostProcessor.postProcessProperties和InstantiationAwareBeanPostProcessor.postProcessPropertyValues。此处用于做属性填充,截图如下:

第七处
回到doCreateBean中继续往下,进入initializeBean方法,此方法中也有两处调用,在applyBeanPostProcessorsBeforeInitialization中调用了第七处:BeanPostProcessor.postProcessBeforeInitialization。
调用的是通常意义上BeanPostProcessor的before方法

第八处
在applyBeanPostProcessorsAfterInitialization中调用了第八处:BeanPostProcessor.postProcessAfterInitialization。调用的是通常意义上BeanPostProcessor的after方法

Spring的切面就是基于此方法进行的,调用的实现方法是AbstractAutoProxyCreator#postProcessAfterInitialization。它会先将切面类放入advisedBeans中,标记为true,表示需要用切面拦截。然后调用AbstractAutoProxyCreator#createProxy方法生成代理。
第九处
第九处是在执行AbstractApplicationContext#close方法销毁bean时触发的,最终调用到的是DisposableBeanAdapter#destroy,在此方法中调用了:DestructionAwareBeanPostProcessor.postProcessBeforeDestruction。用于在销毁bean之前做操作。为什么DestructionAwareBeanPostProcessor中没有after方法?因为执行after的时候所有bean都没了,Spring认为你也没必要做什么扩展了。

小结
以上就是Spring的bean声明周期内经手的9处后置处理器调用,共涉及到5个接口,本文只是简要说明了其作用,其真实的使用场景很多,需要后续慢慢摸索。

Spring的BeanPostProcessor后置处理器与bean的生命周期的更多相关文章
- Spring之BeanPostProcessor(后置处理器)介绍
为了弄清楚Spring框架,我们需要分别弄清楚相关核心接口的作用,本文来介绍下BeanPostProcessor接口 BeanPostProcessor 该接口我们也叫后置处理器,作用是在Be ...
- Spring点滴五:Spring中的后置处理器BeanPostProcessor讲解
BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化.配置以及其他初始化方法前后要添加一些自己逻辑处理.我们需要定义一个或多个BeanPostProcesso ...
- 【Spring注解驱动开发】关于BeanPostProcessor后置处理器,你了解多少?
写在前面 有些小伙伴问我,学习Spring是不是不用学习到这么细节的程度啊?感觉这些细节的部分在实际工作中使用不到啊,我到底需不需要学习到这么细节的程度呢?我的答案是:有必要学习到这么细节的程度,而且 ...
- spring学习四:Spring中的后置处理器BeanPostProcessor
BeanPostProcessor接口作用: 如果我们想在Spring容器中完成bean实例化.配置以及其他初始化方法前后要添加一些自己逻辑处理.我们需要定义一个或多个BeanPostProcesso ...
- Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理
Spring Ioc源码分析系列--Ioc容器注册BeanPostProcessor后置处理器以及事件消息处理 前言 上一篇分析了BeanFactoryPostProcessor的作用,那么这一篇继续 ...
- spring利用后置处理器初始化bean属性
spring利用后置处理器初始化bean属性 参考:http://blog.csdn.net/heyutao007/article/details/50326793 @Configurable @En ...
- BeanPostProcessor后置处理器原理以及ApplicationListener原理
BeanPostProcessor:bean后置处理器,bean创建对象初始化前后进行拦截工作的 1.BeanFactoryPostProcessor:BeanFactory的后置处理器; 在Bean ...
- Spring 如何保证后置处理器的执行顺序 - OrderComparator
Spring 如何保证后置处理器的执行顺序 - OrderComparator Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.htm ...
- Spring第三天,详解Bean的生命周期,学会后让面试官无话可说!
点击下方链接回顾往期 不要再说不会Spring了!Spring第一天,学会进大厂! Spring第二天,你必须知道容器注册组件的几种方式!学废它吊打面试官! 今天讲解Spring中Bean的生命周期. ...
随机推荐
- c++中单引号和双引号的区别
在C++中单引号表示字符,双引号表示字符串. 例如 :在定义一个数组的时候string a [5]={"nihao","henhao","good&q ...
- python中'0b111'中的b 是什么意思
https://zhidao.baidu.com/question/987330764742072579.html binary,二进制的意思
- Intellj IDEA14上用Debug启动项目启动不了:Unable to open debugger port: java.net.SocketException "socket closed"
详情见上图更清晰 15:11:10 Application Server was not connected before run configuration stop, reason: Unable ...
- canvas简单动画
实现场景:定义一个1000*800的方框,圆球在其中移动,碰撞到边框弹回的动画.方框背景是半径为10的小圆球组成.鼠标移动到移动圆球时,圆球停止运动. html代码: <div> < ...
- Android教程 -04 启动其它Activity,静态工厂设计模式传递数据
视频建议采用超清模式观看, 欢迎点击订阅我的优酷 意图 Intent 一个应用程序肯定不只有一个界面,如何切换到其它界面,只时候就需要启动其它的Activity.启动Activity有多种方式.我在这 ...
- Project Euler Problem 16-Power digit sum
直接python搞过.没啥好办法.看了下别人做的,多数也是大数乘法搞过. 如果用大数做的话,c++写的话,fft优化大数乘法,然后快速幂一下就好了.
- 使用php函数ini_set()重新设置某个配置的设置值
使用PHP的ini_set()函数 ini_set (PHP 4, PHP 5, PHP 7) ini_set — 为一个配置选项设置值 说明 string ini_set ( string $var ...
- Python __call__详解
可以调用的对象 关于 __call__ 方法,不得不先提到一个概念,就是可调用对象(callable),我们平时自定义的函数.内置函数和类都属于可调用对象,但凡是可以把一对括号()应用到某个对象身上都 ...
- 【Learning Notes】线性链条件随机场(CRF)原理及实现
1. 概述条件随机场(Conditional Random Field, CRF)是概率图模型(Probabilistic Graphical Model)与区分性分类( Discriminative ...
- pytorch nn.LSTM()参数详解
输入数据格式:input(seq_len, batch, input_size)h0(num_layers * num_directions, batch, hidden_size)c0(num_la ...