【十八】Spring IOC 总结之getBean主流程和各个扩展点总结

一、getBean的流程简介

Spring IOC主要分为两个大的部分,一部分是IOC容器的启动,另一部分是getBean

getBean的部分我盗个图

图一来自https://juejin.im/post/5dec9fe76fb9a01608236cd3

【十八】Spring IOC 总结之getBean主流程和各个扩展点总结_第1张图片

1.简单的讲spring bean的生命周期

1.实例化 Instantiation  (上图中的createBeanInstance:利用构造方法等途径new出实例)

2.属性赋值 Populate (上图中的populateBean:往实例中注入各个属性)

3.初始化 Initialization (上图中的initializeBean:对实例进行一些后续初始化工作)

4.销毁 Destruction

而在这1.2.3.件事的前后都有很多postProcessor和Aware可对bean做扩展 

2.对上图getBean的顺序总结:

1.最外层createBean方法中

利用BeanPostProcessor中的InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation

(如果有代理对象返回则直接调用每个BeanPostProcessor.postProcessAfterInitialization返回了,不需要调用后面的doCreateBean实例化了)

AbstractAutoProxyCreator就是一个InstantiationAwareBeanPostProcessor,它在这里会被调用

2.实例化阶段createBeanInstance

从该阶段开始到结束,这些逻辑都在doCreateBean方法中

通过determineCandidateConstructors确定构造方法

如果没有则使用无参构造方法

如果有工厂方法,则使用构造方法或工厂方法创建bean 

instantiateUsingFactoryMethod(beanName, mbd, args);

3.利用BeanPostProcessor中的MergedBeanDefinitionPostProcess回调postProcessMergedBeanDefinition合并bean定义

applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);

4.加入三级缓存singletonFactories,如果该三级缓存被使用,它会调用所有BPP的getEarlyBeanReference返回早期暴露,例如AbstractAutoProxyCreator进行代理

5.populateBean填充阶段

1.InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(允许用户在Bean注入属性前改变BeanDefinition的信息)

2.autowireByName或者autowireByType (用于在配置文件中通过配置的属性并且显示在配置文件中配置了autowireMode属性)

3.InstantiationAwareBeanPostProcessor.postProcessPropertyValues   ( @Autowire @Resource @Value @Inject 等注解的依赖注入过程,实际执行依赖注入逻辑的是AutowiredAnnotationBeanPostProcessor#postProcessPropertyValues)

4.applyPropertyValues  (注入配置文件中配置的属性,早就不用XML配置文件来配置Bean的属性了)

注:InstantiationAwareBeanPostProcessor接口至此三个方法都执行了

6.initializeBean初始化阶段

1.执行Aware 方法 invokeAwareMethods(beanName, bean);

这里面执行了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware三个接口的实现方法

2.调用每个BeanPostProcessor类的postProcessBeforeInitialization方法

其中ApplicationContextAwareProcessor#postProcessBeforeInitialization会调用invokeAwareInterfaces方法它会调用这几种Aware的实现

EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware

3.invokeInitMethods执行初始化方法

设置Bean的初始化方法有两种方法,一种是在xml或者@Bean指定init-method方法。另一种是让bean实现InitializingBean接口重写afterPropertiesSet()方法。

此方法中的执行逻辑是:

先执行InitializingBean接口的afterPropertiesSet方法,再进行init-method

4.调用每一个BeanPostProcessorpostProcessAfterInitialization方法

AbstractAutoProxyCreator就是一个BeanPostProcessor,它在这里会被调用

7.最后一个是关于早期暴露的处理

通过getSingleton(String,false),从一级或者二级缓存里取出已经暴露的实例

如果没有早期暴露过则返回实例

如果有早期暴露:

原实例未经postProcessAfterInitialization代理(即在早期暴露的时候已经被代理过),则用早期暴露的实例返回

否则经过postProcessAfterInitialization代理,且被其他实例所依赖,即存在多个动态代理的循环依赖(如@Transactional和@Async一起使用),则抛出异常

二、整个getBean中各个扩展点的介绍

扩展点图

【十八】Spring IOC 总结之getBean主流程和各个扩展点总结_第2张图片

可以看到扩展主要用到两个大类的接口: 

1.BeanPostProcessor    作用于实例化、初始化阶段的前后。实现了这些接口的Bean会切入到多个Bean的生命周期中,例如自动注入以及AOP的实现都和他们有关

2.Aware,所有的Aware方法都是在初始化方法之前被调用完

1.BeanPostProcessor中多个拓展点的调用时机

Spring中提供了若干个BeanPostProcessor接口(下称BPP),BPP提供了在不同的时间点让用户对bean进行自定义调整的机会,大多数都在图一用黄色泡泡特别标示了,有以下几种BPP接口比较常用:

InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation:实例化前的操作

MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition:可对BeanDefinition添加额外的自定义配置

InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation:在populateBean前用户可以手动注入一些属性

InstantiationAwareBeanPostProcessor#postProcessPropertyValues:对属性进行注入,例如配置文件加密信息在此解密后注入

BeanPostProcessor#postProcessBeforeInitialization:属性注入后的一些额外操作

BeanPostProcessor#postProcessAfterInitialization:实例完成创建的最后一步,这里也是一些BPP进行代理的时机

SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference:返回早期暴露的bean引用,一个典型的例子是循环依赖时如果有动态代理,需要在此先返回代理实例

2.Aware 

只调用一次的接口

又可以分为两类:

Aware类型的接口

生命周期接口

2.1Aware类型的接口

作用就是让我们能够拿到Spring容器中的一些资源。

Aware之前的名字就是可以拿到什么资源,例如BeanNameAware可以拿到BeanName。

调用时机需要注意:所有的Aware方法都是在初始化阶段之前调用的
Aware接口具体可以分为两组

Aware Group1

  1. BeanNameAware
  2. BeanClassLoaderAware
  3. BeanFactoryAware

Aware Group2

  1. EnvironmentAware
  2. EmbeddedValueResolverAware 实现该接口能够获取Spring EL解析器,用户的自定义注解需要支持spel表达式的时候可以使用,非常方便。
  3. ResourceLoaderAware
  4. ApplicationEventPublisherAware
  5. MessageSourceAware
  6. ApplicationContextAware(ResourceLoaderAware\ApplicationEventPublisherAware\MessageSourceAware) 这几个接口可能让人有点懵,实际上这几个接口可以一起记,其返回值实质上都是当前的ApplicationContext对象,因为ApplicationContext是一个复合接口

可以看到并不是所有的Aware接口都使用同样的方式调用。

Bean××Aware都是在代码中直接调用的,

而ApplicationContext相关的Aware都是通过BeanPostProcessor类的ApplicationContextAwareProcessor#postProcessBeforeInitialization()实现的。

2.2简单的两个生命周期接口

至于剩下的两个生命周期接口就很简单了,实例化和属性赋值都是Spring帮助我们做的,能够自己实现的有初始化和销毁两个生命周期阶段。

1.InitializingBean接口的afterPropertiesSet方法

对应生命周期的初始化阶段,在源码的invokeInitMethods(beanName, wrappedBean, mbd)方法中调用。
有一点需要注意,因为Aware方法都是执行在初始化方法之前,所以可以在初始化方法中放心大胆的使用Aware接口获取的资源,这也是我们自定义扩展Spring的常用方式。

除了实现InitializingBean接口之外还能通过注解或者xml配置的方式指定初始化方法,至于这几种定义方式的调用顺序其实没有必要记。因为这几个方法对应的都是同一个生命周期,只是实现方式不同,我们一般只采用其中一种方式。

2.DisposableBean接口的destroy方法

 类似于InitializingBean,对应生命周期的销毁阶段

以ConfigurableApplicationContext#close()方法作为入口,

实现是通过循环取所有实现了DisposableBean接口的Bean然后调用其destroy()方法 。

你可能感兴趣的:(Spring源码分析,spring,bean声明周期,getBean主流程,getBean扩展点总结)