Spring官网阅读(十)Spring中Bean的生命周期(下)
文章目录
在上篇文章中,我们已经对Bean的生命周期做了简单的介绍,主要介绍了整个生命周期中的初始化阶段以及基于容器启动停止时
LifeCycleBean的回调机制,另外对Bean的销毁过程也做了简单介绍。但是对于整个Bean的生命周期,这还只是一小部分,在这篇文章中,我们将学习完成剩下部分的学习,同时对之前的内容做一次复习。整个Bean的生命周期,按照我们之前的介绍,可以分为四部分
- 实例化
- 属性注入
- 初始化
- 销毁
本文主要介绍实例化及属性注入阶段
生命周期概念补充
虽然我们一直说整个Bean的生命周期分为四个部分,但是相信很多同学一直对Bean的生命周期到底从哪里开始,到哪里结束没有一个清晰的概念。可能你会说,不就是从实例化开始,到销毁结束吗?当然,这并没有错,但是具体什么时候算开始实例化呢?什么时候又算销毁呢?这个问题你是否能清楚的回答呢?如果不能,请继续往下看。
笔者认为,整个Spring中Bean的生命周期,从第一次调用后置处理器中的applyBeanPostProcessorsBeforeInstantiation方法开始的,这个方法见名知意,翻译过来就是在实例化之前调用后置处理器。而applyBeanPostProcessorsAfterInitialization方法的调用,意味着Bean的生命周期中创建阶段的结束。对于销毁没有什么歧义,就是在调用对应Bean的销毁方法就以为着这个Bean走到了生命的尽头,标志着Bean生命周期的结束。那么结合上篇文章中的结论,我现在把Bean的生命周期的范围界定如下:

需要注意的是,对于BeanDefinion的扫描,解析,验证并不属于Bean的生命周期的一部分。这样清晰的界定Bean的生命周期的概念是很有必要的,也许刚刚开始对于我们而言,Bean的生命周期就是一团乱麻,但是至少现在我们已经抓住了线头。而整个Bean的生命周期,我将其分为了两部分
- 创建
- 销毁
对于销毁阶段,我们不需要过多关注,对于创建阶段,开始的标志行为为:applyBeanPostProcessorsBeforeInstantiation方法执行,结束的标志行为为:applyBeanPostProcessorsAfterInitialization方法执行。
基于上面的结论,我们开始进行接下来的分析对于本文中代码的分析,我们还是参照下面这个图

实例化
整个实例化的过程主要对于上图中的3-11-6-4(createBean)以及3-11-6-4-1(doCreateBean)步骤
createBean流程分析
代码如下:
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
// 第一步:解析BeanDefinition中的beanClass属性
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
try {
// 第二步:处理lookup-method跟replace-method,判断是否存在方法的重载
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// 第三步:判断这个类在之后是否需要进行AOP代理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 开始创建Bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
可以看到,第一步跟第二步还是在对BeanDefinition中的一些属性做处理,它并不属于我们Bean的生命周期的一部分,我们直接跳过,接下来看第三步的代码:
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// 不是合成类,并且有实例化后置处理器。这个判断基本上恒成立
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 获取这个BeanDefinition的类型
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
// 这里执行的主要是AbstractAutoProxyCreator这个类中的方法,决定是否要进行AOP代理
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
// 这里执行了一个短路操作,如果在这个后置处理中直接返回了一个Bean,那么后面相关的操作就不会执行了,只会执行一个AOP的代理操作
if (bean != null) {
// 虽然这个Bean被短路了,意味着不需要经过后面的初始化阶段,但是如果需要代理的话,还是要进行AOP代理,这个地方的短路操作只是意味着我们直接在后置处理器中提供了一个准备充分的的Bean,这个Bean不需要进行初始化,但需不需要进行代理,任然由AbstractAutoProxyCreator的applyBeanPostProcessorsBeforeInstantiation方法决定。在这个地方还是要调用一次Bean的初始化后置处理器保证Bean被完全的处理完
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
// bean != null基本会一直返回false,所以beforeInstantiationResolved这个变量也会一直为false
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
对于AbstractAutoProxyCreator中applyBeanPostProcessorsBeforeInstantiation这个方法的分析我们暂且不管,等到AOP学习阶段在进行详细分析。我们暂且只需要知道这个方法会决定在后续中要不要为这个Bean产生代理对象。
doCreateBean流程分析
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 第一步:单例情况下,看factoryBeanInstanceCache这个缓存中是否有
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 第二步:这里创建对象
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 第三步:后置处理器处理
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
// 省略异常处理
}
mbd.postProcessed = true;
}
}
// 循环引用相关,源码阅读阶段再来解读这段代码,暂且就关注以下后置处理器的调用时机
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 第四步:调用后置处理器,早期曝光一个工厂对象
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
try {
// 第五步:属性注入
populateBean(beanName, mbd, instanceWrapper);
// 第六步:初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
// 省略异常处理
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
// 省略异常处理
}
}
}
}
try {
// 第七步:注册需要销毁的Bean,放到一个需要销毁的Map中(disposableBeans)
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
// 省略异常处理
}
return exposedObject;
}
第一步:factoryBeanInstanceCache什么时候不为空?
if (mbd.isSingleton()) {
// 第一步:单例情况下,看factoryBeanInstanceCache这个缓存中是否有
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
这段代码深究起来很复杂,我这里就单纯用理论解释下:
假设我们现在有一个IndexService,它有一个属性A,代码如下:
@Component
public class IndexService {
@Autowired
A a;
public A getA() {
return a;
}
}
而这个A又是采用FactroyBean的形式配置的,如下:
@Component
public class MyFactoryBean implements SmartFactoryBean {
@Override
public A getObject() throws Exception {
return new A();
}
@Override
public Class<?> getObjectType() {
return A.class;
}
// 这个地方并不一定要配置成懒加载,这里只是为了让MyFactoryBean这个Bean在IndexService之后实例化
@Override
public boolean isEagerInit() {
return false;
}
}
我们思考一个问题,在上面这种场景下,当IndexService要完成属性注入时,Spring会怎么做呢?
Spring现在知道IndexService要注入一个类型为A的属性,所以它会遍历所有的解析出来的BeanDefinition,然后每一个BeanDefinition中的类型是不是A类型,类似下面这样:
for (String beanName : this.beanDefinitionNames) {
// 1.获取BeanDefinition
// 2.根据BeanDefinition中的定义判断是否是一个A
}
上面这种判断大部分情况下是成立的,但是对于一种特殊的Bean是不行的,就是我们之前介绍过的FactoryBean,因为我们配置FactoacryBean的目的并不是直接使用FactoryBean这个Bean自身,而是想要通过它的getObject方法将一个对象放到Spring容器中,所以当我们遍历到一个BeanDefinition,并且这个BeanDefinition是一个FactoacryBean时就需要做特殊处理,我们知道FactoacryBean中有一个getObjectType方法,通过这个方法我们可以得到要被这个FactoacryBean创建的对象的类型,如果我们能调用这个方法的话,那么我们就可以来判断这个类型是不是一个A了。
但是,在我们上面的例子中,这个时候MyFactoryBean还没有被创建出来。所以Spring在这个时候会去实例化这个MyFactoryBean,然后调用其getObjectType方法,再做类型判断,最后进行属性注入,伪代码如下:
for (String beanName : this.beanDefinitionNames) {
// 1.获取BeanDefinition
// 2.如果不是一个FactoacryBean,直接根据BeanDefinition中的属性判断
if(不是一个FactoacryBean){
//直接根据BeanDefinition中的属性判断是不是A
}
// 3.如果是一个FactoacryBean
if(是一个FactoacryBean){
// 先创建这个FactoacryBean,然后再调用getObjectType方法了
}
}
大家可以根据我们上面的代码自己调试,我这里就不放debug的截图了。
第二步:创建对象(createBeanInstance)
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 获取到解析后的beanClass
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 忽略异常处理
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 获取工厂方法,用于之后创建对象
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 原型情况下避免多次解析
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}
// 跟后置处理器相关,我们主要关注这行代码
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// 默认使用无参构造函数创建对象
return instantiateBean(beanName, mbd);
}
在创建对象的时候,其余的代码我们暂时不做过多关注。我们暂且知道在创建对象的过程中,Spring会调用一个后置处理器来推断构造函数。
第三步:applyMergedBeanDefinitionPostProcessors
应用合并后的BeanDefinition,Spring自身利用这点做了一些注解元数据的缓存。
我们就以AutowiredAnnotationBeanPostProcessor这个类的对应方法看一下其大概作用
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 这个方法就是找到这个正在创建的Bean中需要注入的字段,并放入缓存中
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
第四步:getEarlyBeanReference
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
// 在这里保证注入的对象是一个代理的对象(如果需要代理的话),主要用于循环依赖
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
属性注入
第五步:属性注入(populateBean)
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
// 省略异常
}
else {
return;
}
}
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { // 主要判断之后是否需要进行属性注入
continueWithPropertyPopulation = false;
break;
}
}
}
}
if (!continueWithPropertyPopulation) {
return;
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 自动注入模型下,找到合适的属性,在后续方法中再进行注入
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 精确注入下,在这里完成属性注入
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
// 一般不会进行这个方法
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
if (needsDepCheck) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
checkDependencies(beanName, mbd, filteredPds, pvs);
}
if (pvs != null) {
// XML配置,或者自动注入,会将之前找到的属性在这里进行注入
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
在上面整个流程中,我们主要关注一个方法,postProcessProperties,这个方法会将之前通过postProcessMergedBeanDefinition方法找到的注入点,在这一步进行注入。完成属性注入后,就开始初始化了,初始化的流程在上篇文章中已经介绍过了,这里就不再赘述了。
总结
在这两篇文章中,我们已经对Bean的全部的生命周期做了详细分析,当然,对于一些复杂的代码,暂时还没有去深究,因为之后打算写一系列专门的源码分析文章。大家可以关注我后续的文章。对于整个Bean的生命周期可以总结画图如下

首先,整个Bean的生命周期我们将其划分为两个部分
- 创建
- 销毁
对于创建阶段,我们又将其分为三步
- 实例化
- 属性注入
- 初始化
我们可以看到,在整个过程中BeanPostPorcessor穿插执行,辅助Spring完成了整个Bean的生命周期。
Spring官网阅读(十)Spring中Bean的生命周期(下)的更多相关文章
- 7 -- Spring的基本用法 -- 9...容器中Bean的生命周期
7.9 容器中Bean的生命周期 Spring可以管理singleton作用域的Bean的生命周期,Spring可以精确地知道该Bean何时被创建,何时被初始化完成.容器何时准备销毁该Bean实例. ...
- Spring官网阅读(十三)ApplicationContext详解(下)
文章目录 BeanFactory 接口定义 继承关系 接口功能 1.HierarchicalBeanFactory 2.ListableBeanFactory 3.AutowireCapableBea ...
- Spring官网阅读(十六)Spring中的数据绑定
文章目录 DataBinder UML类图 使用示例 源码分析 bind方法 doBind方法 applyPropertyValues方法 获取一个属性访问器 通过属性访问器直接set属性值 1.se ...
- Spring官网阅读 | 总结篇
接近用了4个多月的时间,完成了整个<Spring官网阅读>系列的文章,本文主要对本系列所有的文章做一个总结,同时也将所有的目录汇总成一篇文章方便各位读者来阅读. 下面这张图是我整个的写作大 ...
- Spring官网阅读(十八)Spring中的AOP
文章目录 什么是AOP AOP中的核心概念 切面 连接点 通知 切点 引入 目标对象 代理对象 织入 Spring中如何使用AOP 1.开启AOP 2.申明切面 3.申明切点 切点表达式 excecu ...
- Spring官网阅读(十七)Spring中的数据校验
文章目录 Java中的数据校验 Bean Validation(JSR 380) 使用示例 Spring对Bean Validation的支持 Spring中的Validator 接口定义 UML类图 ...
- Spring(十二):IOC容器中Bean的生命周期方法
IOC容器中Bean的生命周期方法 1)Spring IOC容器可以管理Bean的声明周期,Spring允许在Bean生命周期的特定点执行定制的任务. 2)Spring IOC容器对Bean的生命周期 ...
- 你知道Spring是怎么将AOP应用到Bean的生命周期中的吗?
聊一聊Spring是怎么将AOP应用到Bean的生命周期中的? 本系列文章: 听说你还没学Spring就被源码编译劝退了?30+张图带你玩转Spring编译 读源码,我们可以从第一行读起 你知道Spr ...
- Spring中 bean的生命周期
为什么要了解Spring中 bean的生命周期? 有时候我们需要自定义bean的创建过程,因此了解Spring中 bean的生命周期非常重要. 二话不说先上图: 在谈具体流程之前先看看Spring官方 ...
随机推荐
- niuke --abc
链接:https://ac.nowcoder.com/acm/contest/1083/A来源:牛客网 给出一个字符串s,你需要做的是统计s中子串”abc”的个数.子串的定义就是存在任意下标a< ...
- Python的6种方式实现单例模式
单例模式是一个软件的设计模式,为了保证一个类,无论调用多少次产生的实例对象,都是指向同一个内存地址,仅仅只有一个实例(只有一个对象). 实现单例模式的手段有很多种,但总的原则是保证一个类只要实例化一个 ...
- SQLi —— 逗号,空格,字段名过滤突破
前言 出于上海大学生网络安全大赛的一道easysql,促使我积累这篇文章.因为放了大部分时间在Decade和Babyt5上,easysql一点没看,事后看了WP,发现看不懂怎么回事,于是了解了一番. ...
- 被折磨致死的heroku——herku部署
最近一直在弄heroku部署上线,但是因为中国墙和英语问题,一直弄不好,,很是烦躁,所有暂时先放弃了,但是因为查询了一些资料,有些文档链接有必要放到下面,方便各位和自己查看: heroku官方网站: ...
- SpringCloud(五)学习笔记之Hystrix
在微服务架构中多层服务之间会相互调用,如果其中有一层服务故障了,可能会导致一层服务或者多层服务故障,从而导致整个系统故障.这种现象被称为服务雪崩效应. Hystrix组件就可以解决此类问题,Hystr ...
- 5、flink常见函数使用及自定义转换函数
代码地址:https://gitee.com/nltxwz_xxd/abc_bigdata 一.flink编程方法 获取执行环境(execution environment) 加载/创建初始数据集 对 ...
- 微信自动关闭内置浏览器页面,返回公众号窗口 WeixinJSBridge.call('closeWindow')
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- 2019-2020-1 20199326《Linux内核原理与分析》第八周作业
可执行程序工作原理## 编译链接的过程### 示例程序hello.c #include<stdio.h> void main() { printf("Hello world\n& ...
- PIL库的学习总结及生成GIF
一.PIL库的概述 PIL(Python Image Library)库是Python语言的第三方库,需要通过pip工具安装. 打开cmd,输入 pip install pillow PIL库支持图像 ...
- 后缀数组SA
复杂度:O(nlogn) 注:从0到n-1 const int maxn=1e5; char s[maxn]; int sa[maxn],Rank[maxn],height[maxn],rmq[max ...