美文网首页
Bean的生命周期和Bean后置处理器

Bean的生命周期和Bean后置处理器

作者: pq217 | 来源:发表于2022-02-18 19:54 被阅读0次

简述

这篇文章参照spring源码来了解一下bean的创建过程,本文的内容我在学习时画了一张图流程图,结合图和源码会比较直观

BeanFactory

bean工厂,一个创建bean的地方,他的主要方法是getBean,如果已经生产过就直接返回,如果没有就生产后再返回
其中生产bean走得就是createBean方法,也是本位主要要介绍的方法
同时为了可以支持个性化生产bean的过程,spring使用的bean工厂又支持添加bean后置处理器,并且多种类型,不同类型再bean生产的不同时期调用

private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();

用户通过添加后置处理器可以再某一个特定的生命周期参与bean的创建过程

createBean

这里开始跟踪createBean源码,分析重点操作的方法,首先有一句

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
    return bean;
}

这里先走了resolveBeforeInstantiation,如果有返回直接返回bean,后续所有代码全部短路,那么就看一下resolveBeforeInstantiation是干嘛

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    // bean定义的beforeInstantiationResolved属性是true
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // 如果有InstantiationAwareBeanPostProcessor类型的后置处理器
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                // 执行这些后置处理器(InstantiationAwareBeanPostProcessor)
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                if (bean != null) {
                    // 如果创建出bean,再执行BeanPostProcessorsAfterInitialization后置处理器
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}

总结就是这里开始执行InstantiationAwareBeanPostProcessor类型的后置处理器postProcessBeforeInstantiation方法,给用户一个机会使用它来完全自定义创建bean,最终如果创建出来了,只执行一个postProcessAfterInitialization类型的后置处理器(这个后置处理器是实例化之后执行的,不管通过哪种方式,最终都会执行)就反回了。
看spring的注释是这么说的:Typically used to suppress default instantiation for specific target beans(通常用于抑制特定目标 bean 的默认实例化),也就是说用户如果有些特殊的bean不想按工程创建的套路生产,可以使用这种后置处理器来按自己的套路生产bean(这里我不知道spring有什么场景会使用它,以后再说)

doCreateBean

一般情况下,用户还是走工厂的套路去创建bean,所以当resolveBeforeInstantiation返回null时,就开始按工厂的套路创建bean了,也就是doCreateBean方法

image.png
下面开始进入doCreateBean方法,还是只关注主干代码,下面的代码都是从源码贴出,只是贴重点

1.createBeanInstance

instanceWrapper = createBeanInstance(beanName, mbd, args);

这一步开始实例化bean,注意实例化和初始化的区别,简单实例化就是new,初始化就是执行一些初始化方法
这个方法也不用多说了,就是使用反射去创建对象(如果有构造方法注入这里还会更复杂,暂不讨论)

2.applyMergedBeanDefinitionPostProcessors

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

执行MergedBeanDefinitionPostProcessor类型的后置处理器,传出BeanDefinition,beanName,beanType,可以修改BeanDefinition或干点其他事

3.addSingletonFactory

addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

添加三级缓存,对bean工厂三级缓存不懂得可以参考手写Spring之BeanFactory(三级缓存),这里添加的是一个工厂方法,如果方法被执行(出现循环依赖),会执行SmartInstantiationAwareBeanPostProcessor后置处理器(主要是应付代理,后面介绍)

4.populateBean

populateBean(beanName, mbd, instanceWrapper);

给bean填充属性,这一步有很多重要子步骤

4.1 postProcessAfterInstantiation
for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
            return;
        }
    }
}

这里也是执行InstantiationAwareBeanPostProcessor的后置处理器,但与上面createBean不同的是执行的是postProcessAfterInstantiation方法,刚才那个postProcessBeforeInstantiation返回的是object,如果有返回代表截断了bean的生产套路自己生产,而这个postProcessAfterInstantiation方法如果返回false也是return,短路了整个populateBean方法,也就是按照自己的套路填充属性(其实他俩的存在都是因为spring已经很多开放的后置处理器可以调整创建过程,但是不免会有些特殊情况,使用spring处理不来,name就可以使用这种短路的方式完全又用户自己掌控创建过程,就好像我们做一个文章编写的系统,给了各种title的输入框,并且可以选择,已经很灵活了,但是也不能覆盖所有用户需求,那就给你个选择,你可以按我们的套路编辑文章,也可以选择使用富文本,爱怎么写怎么写)

4.2 pvs
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

这里获取bean定义中指定的需要填充的属性,后续还可以加,最终一起填充

4.3 autowireByName | autowireByType
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
    MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
    // Add property values based on autowire by name if applicable.
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
        autowireByName(beanName, mbd, bw, newPvs);
    }
    // Add property values based on autowire by type if applicable.
    if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        autowireByType(beanName, mbd, bw, newPvs);
    }
    pvs = newPvs;
}

获取bean定义的依赖注入模式,然后调用autowireByNameautowireByType完成依赖注入
这种依赖注入是bean工厂提供的一种实现依赖注入的功能,但我们平时使用的注解形式依赖注入@Autowired并不是使用这个功能,而是使用下面的4.4
这里如果有依赖注入的属性,并没有实际调用对象的set去赋值,而是存到pvs,还是最终一起填充

4.4 postProcessProperties
// 再次查找InstantiationAwareBeanPostProcessor类型后置处理器
for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        // 执行postProcessProperties方法
        PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
        // 最终覆盖pvs(其实是添加)
        pvs = pvsToUse;
    }
}

还是执行InstantiationAwareBeanPostProcessor后置处理器,执行postProcessProperties,用户可以自定义要填充的属性,并填充到pvs,@Autowired形式的注入就是写了一个这个后置处理器来实现的,一会单独说

4.5 applyPropertyValues
if (pvs != null) {
    applyPropertyValues(beanName, mbd, bw, pvs);
}

如果pvs(要填充的属性)不为空,执行填充(通过反射去set属性值)
这里总结一下pvs数据的来源: 1.bean定义里自带的(4.2) 2.通过bean定义的resolvedAutowireMode去autowire的(4.3) 3.通过后置处理器返回的(4.4)

5.initializeBean

exposedObject = initializeBean(beanName, exposedObject, mbd);

初始化bean,也就是执行初始化方法什么的,进去看看

5.1 invokeAwareMethods
invokeAwareMethods(beanName, bean);

执行aware方法,这个aware翻译成中文就是感知,其实他的作用也挺简单,就是有的bean用户想让产品用有工厂的联系方式(beanFactory的引用),bean在工厂中的名字(BeanName),类加载器(BeanClassLoader),只要你的bean继承了对应的Aware接口,就会给你提供这些信息,比如继承了BeanFactoryAware,再invokeAwareMethods时就会执行setBeanFactory方法并把BeanFactory传出来,至于bean爱保存还是拿着干什么随意。
有三种aware:

  • BeanNameAware 可以获取到BeanName
  • BeanClassLoaderAware 可以获取到BeanClassLoader
  • BeanFactoryAware 可以获取到BeanFactory
5.2 applyBeanPostProcessorsBeforeInitialization
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

执行所有后置处理器的postProcessBeforeInitialization方法,这一步可以获取到这个阶段的bean(wrappedBean里包含,初始化前),并可以返回一个新的bean覆盖原来的bean,比如创建代理

5.3 invokeInitMethods

执行初始化方法,也就是@PostConstruct注解的方法

5.4 applyBeanPostProcessorsAfterInitialization
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

执行所有后置处理器的postProcessBeforeInitialization方法,这一步可以获取到这个阶段的bean(wrappedBean里包含,初始化后),并可以返回一个新的bean覆盖原来的bean,比如创建代理,spring的AOP实现就是再这里加了后置处理用代理bean覆盖了原bean

6.getSingleton

Object earlySingletonReference = getSingleton(beanName, false);
    if (earlySingletonReference != null) {
        if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
        }

这一步主要看看有没有提前暴露,如果有则替换当前的bean,主要解决循环依赖和AOP,一会将循环依赖细说

7.registerDisposableBeanIfNecessary

registerDisposableBeanIfNecessary(beanName, bean, mbd);

这步记录bean,以便销毁时使用

到此整个创建过程就结束了,这是beanFactory创建bean的整个过程,并预留了很多钩子(后置处理器)可以实现各种特殊要求,spring的依赖注入和AOP就是通过添加后置处理器来实现的,流程图

@Autowired(AutowiredAnnotationBeanPostProcessor)

我们平时要实现依赖注入最常用的就是@Autowired,意思要填充属性
通过对bean创建过程代码的分析并没有依靠@Autowired填充属性的代码,但是有通过后置处理器填充属性的逻辑,不错,@Autowired就是依靠一个特定的后置处理器完成属性填充的。
这个后置处理器就是AutowiredAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessor继承了MergedBeanDefinitionPostProcessorInstantiationAwareBeanPostProcessor(其它的先忽略)

image.png
看看分别的实现,做了什么

postProcessMergedBeanDefinition

这个方法是在实例化之后调用


image.png

看看该后置处理器的实现

@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
}

就不细说了,总结就是扫描bean的@Autowired和@Value注解,并通过beanName缓存起来

postProcessProperties

这个实在填充属性时调用


image.png
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    metadata.inject(bean, beanName, pvs);
    return pvs;
}

代码就是获取上一步的缓存,然后给bean设置属性(我记得这一步是直接给bean就设置属性了,pvs并没有变,但我觉得应该先设置pvs,最后统一在applyPropertyValues的时候实际填充属性,这个可以自己看代码去确定)
总之,通过这两步,1.扫描@Autowired存缓存 2.根据缓存依赖注入 就完成了@Autowired的功能

@AOP(AbstractAutoProxyCreator)

AOP功能实现的方式同样也是使用后置处理器,即AbstractAutoProxyCreator,是一个抽象类,但主要的方法都在这里,所以就介绍他
主要实现了SmartInstantiationAwareBeanPostProcessorBeanPostProcessor(其它先忽略)

image.png
看看分别的实现,做了什么

getEarlyBeanReference

这一步调用是出现循环依赖时调用


image.png

看看实现

@Override
public Object getEarlyBeanReference(Object bean, String beanName) {
    // 根据beanName和class生成一个key
    Object cacheKey = getCacheKey(bean.getClass(), beanName);
    // 使用key存储bean
    this.earlyProxyReferences.put(cacheKey, bean);
    // wrapIfNecessary
    return wrapIfNecessary(bean, beanName, cacheKey);
}

主要是按特定的key存了一个缓存,然后执行wrapIfNecessary(其实就是如果设置了代理则创建代理)
如果这一步创建了代理,容器中就已经存放了当前bean的代理,所以bean的创建过程最后如果getSingleton获取到了bean代表提前暴露了,创建了代理所以最终需要返回这个代理的bean对象,也就是

exposedObject = earlySingletonReference;

postProcessAfterInitialization

初始化结束之后执行


image.png

实现

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (this.earlyProxyReferences.remove(cacheKey) != bean) {
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

这里的逻辑是之前走没走getEarlyBeanReference(即有没有提前暴露),如果没走,执行wrapIfNecessary,这里不懂的可以看看手写Spring之BeanFactory(三级缓存)这篇文章

wrapIfNecessary

两个方法都有用到wrapIfNecessary,里面的代码就不贴了,最重要的是一句

Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

即是创建代理,里面的内容就是创建代理的过程,可以参照我之前的Spring AOP系列文章

最后

spring支持注解依赖注入和AOP,但beanFactory本身不能实现这些功能,而是通过后置处理器方式实现的,那是谁把这些后置处理器交给BeanFactory的呐?答案就是ApplicationContext
over~

相关文章

网友评论

      本文标题:Bean的生命周期和Bean后置处理器

      本文链接:https://www.haomeiwen.com/subject/qugakrtx.html