在对于Spring的所有解读中,Bean的生命周期都堪称是重中之重,甚至还有人称Spring就是个治理Bean的容器。Bean的生命周期之所以这么重要,被重复提及,是因为Spring的外围能力,比方对象创立(IOC)、属性注入(DI)、初始化办法的调用、代理对象的生成(AOP)等性能的实现,都是在bean的生命周期中实现的。分明了bean的生命周期,咱们能力晓得Spring的神奇魔法到底是什么,是怎么一步步赋能,让本来一般的java对象,最终变成领有超能力的bean的。

  1. bean的生命周期
     Spring的生命周期大抵分为:创立 -> 属性填充 -> 初始化bean -> 应用 -> 销毁 几个外围阶段。咱们先来简略理解一下这些阶段所做的事件:

创立阶段次要是创建对象,这里咱们看到,对象的创立权交由Spring治理了,不再是咱们手动new了,这也是IOC的概念。
属性填充阶段次要是进行依赖的注入,将以后对象依赖的bean对象,从Spring容器中找进去,而后填充到对应的属性中去。
初始化bean阶段做的事件绝对比较复杂,包含回调各种Aware接口、回调各种初始化办法、生成AOP代理对象也在该阶段进行,该阶段次要是实现初始化回调,前面咱们缓缓剖析。
应用bean阶段,次要是bean创立实现,在程序运行期间,提供服务的阶段。
销毁bean阶段,次要是容器敞开或进行服务,对bean进行销毁解决。

 当然,bean的生命周期中还包含其余的流程,比方裸露工厂对象等,只是相对而言都是为其余性能做伏笔和筹备的,再讲到对应性能时,咱们在做详细分析。
1.1 创立bean
 对象的创立是bean生命周期的第一步,毕竟要先有1能力有0嘛。创建对象的形式有很多,比方 new、反射、clone等等,Spring是怎么创建对象的呢?绝大多数状况下,Spring是通过反射来创建对象的,不过如果咱们提供了Supplier或者工厂办法,Spring也会间接应用咱们提供的创立形式。
 咱们从源码登程,看一下Spring是如何抉择创立形式的:
// 源码位于 AbstractAutowireCapableBeanFactory.java
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 再次解析BeanDefinition的class,确保class曾经被解析
Class<?> beanClass = resolveBeanClass(mbd, beanName);

// 1: 如果提供了Supplier,通过Supplier产生对象
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {

  return obtainFromSupplier(instanceSupplier, beanName);

}

// 2: 如果有工厂办法,应用工厂办法产生对象
// 在@Configration配置@Bean的办法,也会被解析为FactoryMethod
if (mbd.getFactoryMethodName() != null) {

  return instantiateUsingFactoryMethod(beanName, mbd, args);

}
//...省略局部代码
// 3: 推断构造方法
// 3.1 执行后置处理器,获取候选构造方法
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 3.2 须要主动注入的状况
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||

     mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {  return autowireConstructor(beanName, mbd, ctors, args);

}

// 3.3 默认应用没有参数的构造方法
return instantiateBean(beanName, mbd);
}
复制代码
 通过咱们跟踪源码,发现Spring推断创立形式还是比拟聪慧的,具体逻辑是:

先判断是否提供了Supplier,如果提供,则通过Supplier产生对象。
再判断是否提供工厂办法,如果提供,则应用工厂办法产生对象。
如果都没提供,须要进行构造方法的推断,逻辑为:

如果仅有一个构造方法,会间接应用该构造方法(如果构造方法有参数,会主动注入依赖参数)
如果有多个结构参数,会判断有没有加了@Autowired注解的结构参数:

如果没有,Spring默认抉择无参构造方法;
如果有,且有@Autowired(required=true)的构造方法,就会抉择该构造方法;
如果有,然而没有@Autowired(required=true)的构造方法,Spring会从所有加了@Autowired的构造方法中,依据结构器参数个数、类型匹配水平等综合打分,抉择一个匹配参数最多,类型最精确的构造方法。

 对于创立bean时,具体如何抉择构造方法的,本文咱们不具体开展。因为本文宗旨在于剖析bean的生命周期,咱们只须要简略晓得Spring会抉择一个构造方法,而后通过反射创立出对象即可。其实在浏览Spring源码的时候,小伙伴们也肯定要学会抓大放小,重点关注外围流程,细枝末节的中央能够先战术性疏忽,后续有须要时再回过头剖析也不迟,千万不要陷进去,迷失了方向。

 这里给感兴趣的小伙伴附上一张流程图,感兴趣的小伙伴也能够留言,后续咱们也能够独自剖析。

1.2 merged BeanDefinition
 本阶段是Spring提供的一个拓展点,通过MergedBeanDefinitionPostProcessor类型的后置处理器,能够对bean对应的BeanDefinition进行批改。Spring本身也充分利用该拓展点,做了很多初始化操作(并没有批改BeanDefinition),比方查找标注了@Autowired、 @Resource、@PostConstruct、@PreDestory 的属性和办法,不便后续进行属性注入和初始化回调。当然,咱们也能够自定义实现,用来批改BeanDefinition信息或者咱们须要的初始化操作,感兴趣的小伙伴能够自行试一下哦。
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {

  if (bp instanceof MergedBeanDefinitionPostProcessor) {     MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;     bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);  }

}
}
复制代码

1.3 裸露工厂对象
 本阶段次要是将晚期bean对象提前放入到三级缓存singletonFactories中,为循环依赖做反对。在后续进行属性填充时,如果产生循环依赖,能够从三级缓存中通过getObject()获取该bean,实现循环依赖场景下的主动注入。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&

  isSingletonCurrentlyInCreation(beanName));

if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {

  logger.trace("Eagerly caching bean '" + beanName +        "' to allow for resolving potential circular references");

}
// 做循环依赖的反对 将晚期实例化bean的ObjectFactory,增加到单例工厂(三级缓存)中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
复制代码
 该阶段齐全是为了撑持循环依赖的,是Spring为解决循环依赖埋的伏笔,在Bean的生命周期中齐全能够疏忽。这里为了完整性,和小伙伴们简略提及一下。

如果对Spring如何解决循环依赖不是很分明的话,能够看笔者的另一篇文章 聊透Spring循环依赖,详细分析了Spring循环依赖的解决之道,对本阶段的内容也有具体的叙述。

1.4 属性填充
 本阶段实现了Spring的外围性能之一:依赖注入,包含主动注入、@Autowired注入、@Resource注入等。Spring会依据bean的注入模型(默认不主动注入),抉择依据名称主动注入还是依据类型主动注入。而后调用InstantiationAwareBeanPostProcessor#postProcessProperties()实现@Autowired和@Resource的属性注入。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 省略局部代码

// 获取bean的注入类型
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
// 1: 主动注入
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;

}

// 2: 调用BeanPostProcessor,实现@Autowired @Resource属性填充
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {

  if (pvs == null) {     pvs = mbd.getPropertyValues();  }  for (BeanPostProcessor bp : getBeanPostProcessors()) {     if (bp instanceof InstantiationAwareBeanPostProcessor) {        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;        // 重点: 实现@Autowired @Resource属性填充        PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);        if (pvsToUse == null) {           if (filteredPds == null) {              // 须要注入的属性,会过滤掉Aware接口蕴含的属性(通过ignoreDependencyInterface增加)              filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);           }           pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);           if (pvsToUse == null) {              return;           }        }        pvs = pvsToUse;     }  }

}

// 3: 依赖查看

if (needsDepCheck) {

  if (filteredPds == null) {     filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);  }  checkDependencies(beanName, mbd, filteredPds, pvs);

}
// 4: 将属性利用到bean中
if (pvs != null) {

  applyPropertyValues(beanName, mbd, bw, pvs);

}
}
复制代码

对于依赖注入,笔者在 聊透Spring依赖注入 中有详细分析,不分明的小伙伴能够先去感受一下Spring依赖注入的微妙之处。

1.5 初始化bean
 该阶段次要做bean的初始化操作,包含:回调Aware接口、回调初始化办法、生成代理对象等。

invokeAwareMethods():回调BeanNameAware、BeanClassLoaderAware、BeanFactoryAware感知接口。
回调后置处理器的前置办法,其中:

ApplicationContextAwareProcessor: 回调EnvironmentAware、ResourceLoaderAware、ApplicationContextAware、ApplicationEventPublisherAware、MessageSourceAware、EmbeddedValueResolverAware感知接口。
InitDestroyAnnotationBeanPostProcessor:调用了标注了@PostConstruct的办法。

invokeInitMethods()调用初始化办法:

如果bean是InitializingBean的子类, 先调用afterPropertiesSet()。
回调自定义的initMethod,比方通过@Bean(initMethod = "xxx")指定的初始化办法。

回调后置处理器的后置办法,可能返回代理对象。其中AbstractAutoProxyCreator和 AbstractAdvisingBeanPostProcessor都有可能产生代理对象,比方InfrastructureAdvisorAutoProxyCreator实现了@Transactional代理对象的生成,AsyncAnnotationBeanPostProcessor实现了@Async代理对象的生成。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 1: 回调Aware接口中的办法
// 实现Aware办法的回调(BeanNameAware,BeanClassLoaderAware,BeanFactoryAware)
invokeAwareMethods(beanName, bean);

Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {

  // 2: 调用before...办法  // ApplicationContextAwareProcessor: 其余Aware办法的回调  // InitDestroyAnnotationBeanPostProcessor: @PostConstruct办法的回调  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

}

try {

  // 3: 实现xml版本和@bean(initMethod)的init办法回调  invokeInitMethods(beanName, wrappedBean, mbd);

}

// 4: 调用after办法
// 重点: AOP生成代理对象
if (mbd == null || !mbd.isSynthetic()) {

  wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

}

return wrappedBean;
}
复制代码

 在初始化实现后,bean会被放到单例池中,正式开始本人的使命:为我的项目服务,比方接管http申请,进行CRUD等等。后续有应用到该bean的中央,也是间接从单例池中获取,不会再次创立bean(仅单例的哦)。

  1. bean的前因后果
    2.1 bean的扫描阶段
     当初咱们曾经晓得Spring bean是如何创立的了,那什么时候创立这些bean呢,是遵循懒加载的思维,在理论应用的时候在创立吗?其实不是的,因为bean之间的简单关系和生命周期的起因,Spring在容器启动的时候,就会实例化这些bean,而后放到单例池中,即用即取。并且在创立前、创立中、创立后都会做很多查看,确保创立的bean是符合要求的,这些咱们就不赘述了。
     言归正传,仔细的你肯定发现,创立bean时次要是从RootBeanDefinition mbd这个参数获取bean的相干信息的,其实这就是赫赫有名的BeanDefinition,其中封装了对于bean的元数据信息,对于BeanDefinition,后续咱们会独自解说,这里咱们先了解为bean的元数据信息即可。那么这些元数据信息是什么时候解析的呢?
     这就要提到Spring的类扫描了,其大抵流程是:通过ASM字节码技术扫描所有的类 -> 找出须要Sp加了@Compont注解的(简略了解) -> 封装成BeanDefinition -> 寄存到汇合中。后续再实例化bean的时候,就能够遍历这个汇合,获取到BeanDefinition,而后进行bean的创立了。

对于解决类扫描的ConfigurationClassPostProcessor后置处理器以及ConfigurationClassParser和ComponentScanAnnotationParser扫描器的具体细节,后续咱们独自解说,和本章节关系不大,咱们先简略了解即可。

2.2 实例化后回调
 在后面的章节咱们剖析过:在容器中的bean实例化,放到单例池中之后,bean在创立阶段的生命周期就正式实现,进入应用中阶段,开启对完服务之路。的确,这就是创立bean的全过程,如果有小伙伴看过笔者之前的聊Spring事件的那篇文章(聊透Spring事件机制),会发现对于@EventListener处理器的辨认注册,是在afterSingletonsInstantiated阶段实现的。其实这里也是一个拓展点,咱们齐全能够实现SmartInitializingSingleton#afterSingletonsInstantiated(),在bean初始化实现后会回调该办法,进而触发咱们本人的业务逻辑,故这里咱们独自说一下。不分明的小伙伴请移步先去理解一下哦。

2.3 bean的销毁阶段
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

  throws BeanCreationException {

// ...省略代码
try {

  // 为bean注册DisposableBean,在容器敞开时,调用destory()  registerDisposableBeanIfNecessary(beanName, bean, mbd);

}
catch (BeanDefinitionValidationException ex) {

  throw new BeanCreationException(        mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);

}

return exposedObject;
}
复制代码
 在创立bean的时候,会判断如果bean是DisposableBean、AutoCloseable的子类,或者有 destroy-method等,会注册为可销毁的bean,在容器敞开时,调用对应的办法进行bean的销毁。