Bean的生命周期流程-上
Posted 热爱编程的大忽悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bean的生命周期流程-上相关的知识,希望对你有一定的参考价值。
Bean的生命周期流程-上
引言
Spring拥有一套完善的Bean生命周期体系,而使得这套生命周期体系具有高扩展性的关键在于Bean生命周期回调接口,通过这些接口我们可以动态的插入Bean生命周期初始化的各个阶段,然后进行一系列动态代理,自动注入,属性校验的工作。
今天,我们来一起看看Bean的生命周期流程,即getBean流程是怎样实现的。
getBean
AbstractBeanFactory的getBean方法会调用doGetBean方法:
AbstractBeanFactory的doGetBean方法我们只关注单例Bean的创建流程:
protected <T> T doGetBean(
String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException
//获取真正的beanName
//1、如果是FactoryBean,会去掉Bean开头的&符号
// 2、如存在多层别名映射A->B->C->D,传入D,最终会返回A
String beanName = transformedBeanName(name);
Object beanInstance;
//1.尝试从缓存中获取已经实例化好的单例bean
//2.存在循环依赖,从signleFactory中获取提早暴露的bean
Object sharedInstance = getSingleton(beanName);
//缓存中获取到了对应的bean
if (sharedInstance != null && args == null)
if (logger.isTraceEnabled())
//如果singletonsCurrentlyInCreation集合中包含了该beanName
//说明此时获取到的是提早暴露出来的bean--此时存在循环依赖
if (isSingletonCurrentlyInCreation(beanName))
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
else
//说明获取到的是已经实例化好的bean
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
//对factoryBean进行特殊处理--下面会进行解释
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
else
//原型对象不允许循环创建,如果是原型对象正在创建,那就抛异常
if (isPrototypeCurrentlyInCreation(beanName))
throw new BeanCurrentlyInCreationException(beanName);
//如果存在父容器,并且只在子容器中不包含当前bean定义的情况下,才会尝试从父容器中getBean
// 这就是为何,我们扫描controller,哪怕不加排除什么的,也不会出问题的原因~
//因为Spring中的单例Bean只会被实例化一次(即使父子容器都扫描了)
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName))
//和transformedBeanName处理类似,多加了一个获取FactoryBean本身的判断条件
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory)
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
else if (args != null)
return (T) parentBeanFactory.getBean(nameToLookup, args);
else if (requiredType != null)
return parentBeanFactory.getBean(nameToLookup, requiredType);
else
return (T) parentBeanFactory.getBean(nameToLookup);
//在alreadyCreated记录一下当前beanName,表示当前bean已经创建或者将要创建
if (!typeCheckOnly)
markBeanAsCreated(beanName);
...
try
...
//将一开始通过包扫描或者注解扫描等方式得到的不同类型的BeanDefinition都转换为RootBeanDefinition
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//当前beanDefinition不能是抽象的
checkMergedBeanDefinition(mbd, beanName, args);
//如果bean上标注了@DependsOn注解,那么解析的时候会将注解信息都存放到当前BeanDefinition的dependsOn属性中去
String[] dependsOn = mbd.getDependsOn();
//将依赖的bean先进行初始化
if (dependsOn != null)
for (String dep : dependsOn)
//判断是否存在A dependsOn B,然后B又dependsOn A的情况,或者是涉及到更多bean之间的循环依赖
if (isDependent(beanName, dep))
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
//不存在因为@DependsOn注解产生的循环依赖,就正常将依赖的bean进行初始化
registerDependentBean(dep, beanName);
try
getBean(dep);
catch (NoSuchBeanDefinitionException ex)
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
//单例bean的创建过程
if (mbd.isSingleton())
sharedInstance = getSingleton(beanName, () ->
try
return createBean(beanName, mbd, args);
catch (BeansException ex)
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
);
//处理factoryBean的转换情况
beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
//其他scope类型bean的处理
....
catch (BeansException ex)
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
finally
beanCreation.end();
//通过TypeConverter将bean转换为指定的类型
return adaptBeanInstance(name, beanInstance, requiredType);
getSingleton
DefaultSingletonBeanRegistr的getSingleton方法:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory)
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects)
//先尝试从单例缓冲池中获取已经实例化好的bean
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null)
//一般缓存中此时是还没有创建好当前bean的
//如果调用了destroySingletons方法销毁所有单例bean,那么此时bean就不允许再被创建了
if (this.singletonsCurrentlyInDestruction)
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
if (logger.isDebugEnabled())
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
// 创建前置检查:
//1、若在inCreationCheckExclusions里面,表示不需要进行创建中检查
//2、如果需要进行创建中检查,就把当前bean加入singletonsCurrentlyInCreation去,表示这个Bean正在创建中
beforeSingletonCreation(beanName);
boolean newSingleton = false;
...
try
//getObject方法最终调用的是createBean方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
//异常捕获
...
finally
if (recordSuppressedExceptions)
this.suppressedExceptions = null;
// 创建完成后再检查一遍。做的操作为:从正在创建缓存中移除
afterSingletonCreation(beanName);
if (newSingleton)
//将关于当前bean提前暴露出来的bean都清理掉,然后将当前bean加入单例缓冲池中
addSingleton(beanName, singletonObject);
return singletonObject;
createBean
开始创建Bean AbstractAutowireCapableBeanFactory#createBean 提供此方法的抽象类为:AbstractBeanFactory,由子类去实现创建的逻辑。
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException
if (logger.isTraceEnabled())
logger.trace("Creating instance of bean '" + beanName + "'");
RootBeanDefinition mbdToUse = mbd;
// 通过classLoader加载beanDefinition中保存的className得到对应的class
//这一步用于确定对应的bean是可以被实例化的
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null)
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
// Prepare method overrides.
try
// 这里主要是解析<lookup-method name="getFruit" bean="bananer"/>类似这种方式的依赖注入(Spring支持lookup-method,replace-method两个依赖注入的方式)
// 它相当于调用指定类里面的指定方法进行注入,所以需要考虑到方法重载的情况,因此这个方法解析的就是这种情况
// 由于项目中一般这么使用,也非常的不大众,具体原理此处省略
mbdToUse.prepareMethodOverrides();
catch (BeanDefinitionValidationException ex)
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
try
// 从doc解释:给BeanPostProcessors一个机会来返回一个代理对象代替目标对象
// 1、具体逻辑是判断当前Spring容器是否注册了实现了InstantiationAwareBeanPostProcessor接口的后置处理器如果有,则依次调用其中的applyBeanPostProcessorsBeforeInstantiation方法,如果中间任意一个方法返回不为null,直接结束调用。
// 2、applyBeanPostProcessorsBeforeInstantiation返回不为null的情况下,然后依次所有注册的BeanPostProcessor的postProcessAfterInitialization方法。
//默认情况下,默认注册的bean后置处理器,在该处都不会做任何事情
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);
if (logger.isTraceEnabled())
logger.trace("Finished creating instance of bean '" + beanName + "'");
return beanInstance;
...
后置处理器类型区分
BeanPostProcessor和InstantiationAwareBeanPostProcessor这两个接口,是比较容易搞混的,需要这里注意区分一下。
InstantiationAwareBeanPostProcessor代表了Spring的另外一段生命周期:实例化。先区别一下Spring Bean的实例化和初始化两个阶段的主要作用:
- 实例化:实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中
- 初始化:初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性
所以现在就清楚了:InstantiationAwareBeanPostProcessor是作用于 实例化 前后,所以是先执行的。
BeanPostProcessor是作用于 初始化 前后,给Bean各个属性赋值的时候执行的(比如我们的属性依赖注入,都是这个时候生效的)
// Instantiation:[ɪnstænʃɪ'eɪʃən] 实例化,例示
// Initialization:[ɪˌnɪʃəlaɪ'zeɪʃn] 初始化,设定初始值
public interface BeanPostProcessor
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
return bean;
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
return bean;
子接口:InstantiationAwareBeanPostProcessor
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException
return null;
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException
return true;
@Nullable
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException
return pvs;
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException
return null;
ApplicationListenerDetector重点实现了postProcessAfterInitialization方法:将那些实现ApplicationListener接口的bean,在它们初始化之后,将它们注册到applicationContext的事件多播器上。并在这些ApplicationListener bean销毁之前,将它们从applicationContext的事件多播器上移除。
子接口SmartInstantiationAwareBeanPostProcessor 继承自 InstantiationAwareBeanPostProcessor;
但是SmartInstantiationAwareBeanPostProcessor多了三个方法:
// 从名字上,它有个Smart,是比较智能一些的
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
// 预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null
default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException
return null;
// 选择合适的构造器,比如目标对象有多个构造器,在这里可以进行一些定制化,选择合适的构造器
// beanClass参数表示目标实例的类型,beanName是目标实例在Spring容器中的name
// 返回值是个构造器数组,如果返回null,会执行下一个PostProcessor的determineCandidateConstructors方法;否则选取该PostProcessor选择的构造器
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
throws BeansException
return null;
// 获得提前暴露的bean引用。主要用于解决循环引用的问题
// 只有单例对象才会调用此方法
default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException
return bean;
在对bean进行依赖注入时,定位bean实例化使用的构造器,就是通过搜寻容器中所有SmartInstantiationAwareBeanPostProcessor类型后置处理器实现,然后依次调用其determineCandidateConstructors方法对bean进行解析获取的。
默认只有自动代理创建重写了getEarlyBeanReference方法,尝试将提早暴露出来的bean也进行代理。
MergedBeanDefinitionPostProcessor:
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
default void resetBeanDefinition(String beanName)
用来将RootBeanDefinition暴露出来的回调。看看它的一些主要实现:
//InitDestroyAnnotationBeanPostProcessor
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)
LifecycleMetadata metadata = findLifecycleMetadata(beanType);
metadata.checkConfigMembers(beanDefinition);
//CommonAnnotationBeanPostProcessor
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)
super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
//AutowiredAnnotationBeanPostProcessor
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
//ApplicationListenerDetector
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName)
this.singletonNames.put(beanName, beanDefinition.isSingleton());
稍微总结下:
-
InstantiationAwareBeanPostProcessor
接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置 -
postProcessBeforeInstantiation
方法是最先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization
方法会调用,其它方法不再调用;否则按照正常的流程走 -
postProcessAfterInstantiation
方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessPropertyValues
方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck()
);如果该方法返回false,并且不需要check,那么postProcessPropertyValues
就会被忽略不执行;如果返回true,postProcessPropertyValues
就会被执行 -
postProcessPropertyValues
方法对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)。如果postProcessAfterInstantiation
方法返回false,该方法可能不会被调用。可以在该方法内对属性值进行修改 - 以上是关于Bean的生命周期流程-上的主要内容,如果未能解决你的问题,请参考以下文章