前言
Spring 作为 IOC 框架,实现了依赖注入(DI),由一个中心化的 Bean 工厂来负责各个 Bean 的实例化和依赖管理。各个 Bean 可以不需要关心各自的复杂的创建过程,达到了很好的IOC控制反转效果。我们对 Spring 的工作流进行一个粗略的概括,主要为两大环节:
- 解析,读 xml 配置,扫描类文件,从配置或者注解中获取 Bean 的定义信息,注册一些扩展功能。
- 加载,通过解析完的定义信息获取 Bean 实例。
依赖注入DI:通过容器注入了bean对象,而且这个过程是自动的。也就是说容器会自动找到和bean对象匹配的类型实例注入到对象中;
Spring总体流程
我们假设所有的配置和扩展类都已经装载到了 ApplicationContext 中,然后具体的分析一下 Bean 的加载流程。
Spring 进行了抽象和封装,使得作用域和依赖关系的配置对开发者透明,我们只需要知道当初在配置里已经明确指定了它的生命周期和依赖了谁,至于是怎么实现的,依赖如何注入,托付给了 Spring 工厂来管理。
Spring 只暴露了很简单的接口给调用者,比如 getBean
:
ApplicationContext context = new ClassPathXmlApplicationContext("hello.xml");
HelloBean helloBean = (HelloBean) context.getBean("hello");
helloBean.sayHello();
那我们就从 getBean
方法作为入口,去理解 Spring 加载bean的流程是怎样的,以及内部对创建信息、作用域、依赖关系等等的处理细节。
getBean大体流程
上面是跟踪了 getBean 的调用链创建的流程图,为了能够很好地理解 Bean 加载流程,省略一些异常、日志和分支处理和一些特殊条件的判断。
从上面的流程图中,可以看到一个 Bean 加载会经历这么几个阶段(用绿色标记):
- 获取 BeanName,对传入的 name 进行解析,转化为可以从 Map 中获取到 BeanDefinition 的 bean name。
- 合并 Bean 定义,对父类的定义进行合并和覆盖,如果父类还有父类,会进行递归合并,以获取完整的 Bean 定义信息。
- 实例化,使用构造或者工厂方法创建 Bean 实例。
- 属性填充,寻找并且注入依赖,依赖的 Bean 还会递归调用
getBean
方法获取。 - 初始化,调用自定义的初始化方法。
- 获取最终的 Bean,如果是 FactoryBean 需要调用 getObject 方法,如果需要类型转换调用 TypeConverter 进行转化。
Spring IOC大体流程
解释上图:
1、首先当容器启动时,会依据配置或注解扫描指定的包,将其中的类转化为BeanDefinition,并集中在DefaultListableBeanFactory类的beanDefinitionMap变量里。另一种说法:通过BeanDefinitionReader 读取指定的配置文件或注解扫描生成bean的定义信息,然后到完整的bean定义信息(BeanDefinition对象),注意这里只是存储bean的定义信息,还没有实例化bean对象;就像工厂里面一样,原材料已经准备好了,但是还没有进行生产,原材料就是beanDefinition,生产就是实例化。
org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition)beanDefinition).validate();
} catch (BeanDefinitionValidationException var9) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);
}
}
BeanDefinition oldBeanDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!this.isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound.");
}
if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Overriding user-defined bean definition for bean '" + beanName + "' with a framework-generated bean definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if (!beanDefinition.equals(oldBeanDefinition)) {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName + "' with a different definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
} else if (this.logger.isDebugEnabled()) {
this.logger.debug("Overriding bean definition for bean '" + beanName + "' with an equivalent definition: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
this.beanDefinitionMap.put(beanName, beanDefinition);
} else {
if (this.hasBeanCreationStarted()) {
synchronized(this.beanDefinitionMap) {
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
Set<String> updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
} else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || this.containsSingleton(beanName)) {
this.resetBeanDefinition(beanName);
}
}
2、Spring 提供了一种叫做 BeanFactoryPostProcessor
的容器扩展机制
. 该机制允许开发者在容器实例化相应 Bean 对象之前, 对注册到容器的 BeanDefinition 的信息做出修改。即在容器的第一阶段的最后进行一些自定义操作. 比如修改其中 bean 定义的某些属性, 为 bean 定义增加其他信息等。在 BeanDefinition
和 完整BeanDefinition
中间通过一个后置增强器BeanFactoryPostProcessor
,可以对BeanDefinition
信息进行统一修改。
Spring 中自带的 BeanFactoryPostProcessor 接口的实现:
- org.springframework.beans. factory.config.
PropertyPlaceholderConfigurer
占位符机制 - org.springframework.beans.factory. config.
PropertyOverrideConfigurer
重写属性值 - ...
同时也支持开发者通过实现 BeanFactoryPostProcessor 接口自定义扩展,只需要实现 BeanFactoryPostProcessor
接口即可,这个后置增强器是可以有多个的,你只要在不同的类实现多个 BeanFactoryPostProcessor
接口就会执行多次,就像这样:
/**
* 扩展方法--后置增强器(可修改bean的定义信息)
*/
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor{
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 通过 Spring 中 bean 的名字获取到指定的 bean
GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanFactory.getBeanDefinition("user");
// 输出 beanDefinition 的信息
System.out.println(beanDefinition.getBeanClass());
System.out.println(beanDefinition.getFactoryBeanName());
// 然后进行狸猫换太子,将 User 类对应的 BeanDefinition 对象的 beanClass 属性替换掉
beanDefinition.setBeanClass(Good.class);
}
}
可以看到,虽然表面上是通过 getBean("user") 来获取 user 对象,但是实际调用的确实 Good 对象的构造方法,返回的是 good 对象. 但 Good 并没有让 Spring 扫描. 这个例子就展示了如何通过 BeanFactoryPostProcessor 机制插手容器的启动
3、得到完整BeanDefinition
之后就可以进行创建对象了,这整个过程被称为 bean 的生命周期,也就是从实例化到销毁的整个过程;
那么这时候爱学习童鞋就要发问了:“对象创建和销毁有这么麻烦嘛?直接反射实例化一个对象不就行了嘛?为啥还有初始化?”
首先,这是个好问题,来,我们先把掌声送给这位发问的同学;我想说的是,就算是普通的new一个对象出来,里面也会经过实例化和初始化。
BeanDefinition介绍
BeanDefinition是一个接口,在Spring中存在多种实现:RootBeanDefinition、ChildBeanDefinition以及GenericBeanDefinition等均继承了AbstractBeanDefinition,其中BeanDefinition是配置文件< bean>元素标签在容器中的内部表示形式。< bean>元素标签拥有class、scope、lazy-init等配置属性,BeanDefinition则提供了相应的beanClass、scope、lazyInit属性,BeanDefinition和< bean>中的属性是一一对应的,其中RootBeanDefinition是最常用的实现类,它对应一般性的< bean>元素标签,GenericBeanDefinition是自2.5版本以后新加入到bean文件配置属性的定义类,是一站式服务类。
Spring通过BeanDefinition将配置信息转换为容器内部标识,并将这些BeanDefinition注册到BeanDefinitionRegistry中,Spring容器的BeanDefinitionRegistry就像Spring配置信息的内存数据库,主要以map的形式保存,后续的操作直接从BeanDefinitionRegistry中读取配置信息。
注册解析的BeanDefinition
对于配置文件,解析是解析完了,装饰也装饰完了,对于得到的beanDefinition已经可以满足后续的使用要求了,为剩下的工作就是注册了,也就是BeanDefinitionReaderUtils中的org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition 代码如下:
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();// 使用beanName做唯一标识注册
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();// 注册所有的别名
if (aliases != null) {
String[] var4 = aliases;
int var5 = aliases.length;
for(int var6 = 0; var6 < var5; ++var6) {
String alias = var4[var6];
registry.registerAlias(beanName, alias);
}
}
}
FactoryBean的使用
一般情况下,Spring通过反射机制利用bean的class属性指定实现类来实例化bean。在某些情况下,实例化bean过程比较复杂,如果按照传统方式,则需要在< bean>中提取大量的配置信息,配置方式的灵活性是受限的,这时候采用编码的方式可能会得到一个简单方案。Spring为此提供了一个org.SpringFramework.bean.factory.FactoryBean工厂类接口,用户可以通过实现该接口定制实现实例化bean的逻辑。
public interface FactoryBean<T> {
T getObject() throws Exception;//返回有FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例还会放到Spring容器中单实例缓存池中。
boolean isSingleton();//返回有FactoryBean创建的bean实例的作用域是singleton还是prototype。
Class< T> getObjectType() ;返回FactoryBean创建的bean类型。
}
重要点:
【当配置文件中< bean>class属性配饰的实现类是FactoryBean时,通过getBean()方法返回的不是FactoryBean本身,而是FactoryBean#getObject()方法所返回的对象,相当于FactoryBean#getObject()方法代理了getBean()方法。】
Spring Bean的生命周期
准备创建bean->getBean->doGetBean
AbstractBeanFactory#getBean -》AbstractBeanFactory#doGetBean -》AbstractBeanFactory#createBean -》AbstractAutowireCapableBeanFactory#createBean-》AbstractAutowireCapableBeanFactory#doCreateBean
BeanFactory继承关系:
BeanFactory->ConfigurableBeanFactory->AbstractBeanFactory->
AbstractAutowireCapableBeanFactory->DefaultListableBeanFactory
继承关系图:
我们不可能指望在一个函数中完成一个复杂的逻辑,而且我们跟踪了这么多Spring的代码。经历的这么多函数,或多或少也发现一些规律:一个真正干活的函数其实是以do开头的;而给我们错觉的函数,其实只是从全局的角度去做一些统筹的工作。这个规律对于createBean也不例外,那么createBean函数中做了哪些准备工作:
protected Object createBean(final String beanName,final RootBeanDefinition mbd,final Object[] args) throws BeanCreationException
// 锁定class,根据设置的class属性或者根据className来解析Class
// 验证及准备覆盖的方法
// 给BeanPostProcessors一个机会返回代理来替代真正的实例
// 调用doCreateBean()方法
}
注意到在调用AbstractAutowireCapableBeanFactory#doCreateBean之前,调用了resolveBeforeInstantiation方法,下文会介绍到。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) ;
doCreateBean 流程图和简略分析(下文会详细分析)
从流程图上大致可以 得出 doCreateBean 分为如下步骤:
- 首先 判断 是否是单例模式 ,如果是单例模式, 从 缓存 factoryBeanInstanceCache 获取,并将 缓存清楚
- 如果不是 单例模式,或者 缓存没有对应的value , 开始创建 实例,调用createBeanInstance 方法, createBeanInstance 方法 下面详细分析
- 修改 合并之后的 Bean Definition,bean 合并后的处理, Autowired 注解正是通过此方法实现诸如类型的预解析, 主要是 调用了 MergedBeanDefinitionPostProcessor 的postProcessMergedBeanDefinition 方法
- 依赖处理 ,这里有一个放入缓存,以便其他的 依赖此bean 的 , 可以提前获取到, 这里 调用 了 SmartInstantiationAwareBeanPostProcessor 的 getEarlyBeanReference 进行提前 曝光
- 进行填充, 调用了 populateBean方法,将各个属性值注入
- 初始化Bean ,这里 对 各种Aware 设置, 一些前置、后置 、initialzingBean 等相关的处理
- 循环检查,检查是否还有依赖的bean 没有创建
- 注册 disposableBeans 里面,以便在销毁bean 的时候 后置处理也生效
源码分析如下:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
// 如果定义的是单例模式,就先从缓存中清除
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// 如果 instanceWrapper 为空,那就 创建对应的beanInstance,具体方法在下面小节分析
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
// 将 解析类型 设置 为 beanType
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
// 使用后置处理器 对其进行处理
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 这里主要是 MergedBeanDefinitionPostProcessor
//对@Autowire,@Value等这些注解进行处理, 相关的可以
// 参考AutowiredAnnotationBeanPostProcessor 相关逻辑
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
/**是否需要提前曝光: 单例& 允许循环依赖 & 当前bean正在创建中, 检查循环依赖
这里主要是调用 方法addSingletonFactory ,往缓存singletonFactories里面 放入一个 ObjectFactory
当其他的bean 对该bean 有依赖时,可以提前获取到
getEarlyBeanReference方法就是获取一个引用, 里面主要是
调用了 SmartInstantiationAwareBeanPostProcessor,
的 getEarlyBeanReference 方法,以便解决循环依赖问题, 这里 一般都是bean 本身,
在 AOP时 是代理
**/
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加入缓存
// 对bean 再一次依赖引用,主要应用SmartInstantiationAwareBeanPostProcessor
// 其中我们熟悉的AOP就是在这里将advice 动态织入,若没有直接返回bean
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
// 下面就是初始化实例了
try {
// 对bean进行填充,将各个属性值注入,其中可能存在依赖于其他bean的属性,会递归初始化
populateBean(beanName, mbd, instanceWrapper);
//进一步初始化Bean
//注入 Aware 相关的对象
// 调用 后置处理器 BeanPostProcessor 里面的postProcessBeforeInitialization方法
// 调用 initialzingBean,调用实现的 afterPropertiesSet()
// 调用 init-mothod,调用相应的init方法
// 调用 后置处理器 BeanPostProcessor 里面的调用实现的postProcessAfterInitialization方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
earlySingletonReference 只有在检测到有循环依赖的情况下才会不为空
if (earlySingletonReference != null) {
//如果exposedObject 没有在初始化方法中被改变,也就是没有被增强
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);
}
}
/**
因为 bean 创建后其所依赖的bean一定是已经创建,
actualDependentBeans 不为空则表示 当前bean 创建后其依赖的bean 却没有全部创建,
也就是说存在依赖
*/
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
// 注册到 disposableBeans 里面,以便在销毁bean 的时候 可以运行指定的相关业务
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
粗略来看,bean的生命周期主要分为以下4个步骤:
但其实,它的内部蕴含了很多东西,让我们看看细化后的流程图:
怎么样? 是不是看到了很多没见过的东西?接下来我们一个个地讲解,接下来我们要将1、3、4 放到一起讲,是因为它们是在同一个接口里面的。
实例化的前置处理
在真正调用doCreateBean方法创建bean的实例前使用了这样一个方法resolveBeforeInstantiation(beanName,mbd)对BeanDefinition中的属性做前置处理。
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//省略部分代码
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
//正式进入生命周期
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//寻找InstantiationAwareBeanPostProcessor,并执行相应方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
//在返回不为null的情况下,寻找BeanPostProcessor,执行相应方法
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
当resolveBeforeInstantiation返回不为null的bean后,createBean方法会直接return返回。也就是说,后续的实例化、属性赋值与初始化阶段都不会进行。这一步,将会给BeanPostProcessor一个返回代理而不是目前bean的机会。
当然,无论其中是否有相应的逻辑实现我们都可以理解,因为真正的逻辑实现前后留有处理函数也是可扩展的一种体现。但是这并不是最重要的,在函数中还提供了一个短路判断,这才是最关键的部分。
protected Object resolveBeforeInstantiation(String beanName,RootBeanDefinition mbd)
此resolveBeforeInstantiation方法中最吸引人的无疑是两个方法:applyBeanPostProcessBeforeInstantiation以及applyBeanPostProcessAfterInitialization。这两个方法实现非常简单,无非是对后处理器中所有InstantiationAwareBeanPostProcessor类型的后处理器进行postProcessBeforeInstantiation方法和BeanPostProcessAfterInitialization方法的调用。
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
//获取所有BeanPostProcessor的实现类
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//如果属于InstantiationAwareBeanPostProcessor类型,则执行postProcessBeforeInstantiation方法
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//获取所有BeanPostProcessor的实现类
for (BeanPostProcessor processor : getBeanPostProcessors()) {
//挨个执行postProcessAfterInitialization方法
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
实现InstantiationAwareBeanPostProcessor
接口demo,如下代码举例:
@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
// 实例化前置
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("postProcessBeforeInstantiation被调用了----在对象实例化之前调用-----beanName:" + beanName);
// 默认什么都不做,返回null
return null;
}
// 实例化后置
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInstantiation被调用了---------beanName:" + beanName);
//默认返回true,什么也不做,继续下一步
return true;
}
// 属性修改
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
System.out.println("postProcessPropertyValues被调用了---------beanName:"+beanName);
// 此方法可对bean中的属性值进行、添加、修改、删除操作;
// 对属性值进行修改,如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用,
return pvs;
}
}
1、实例化前置
实例化前置使用的是 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation(Class<?> beanClass, String beanName) 方法,方法里有2个参数,分别是beanClass和beanName,顾名思义,就是对在对象实例化之前对bean对象的class信息进行修改或者扩展,以达到我们想要的功能,它的底层是动态代理AOP技术实现的;且是bean生命周期中最先执行的方法;
实例化前的后处理器的应用:
bean的实例化前调用,就是将AbstractBeanDefinition转换为BeanWrapper前的处理,给子类一个修改BeanDefinition的机会,也就是说当程序经过这个方法后,bean可能已经不是我们认识的bean了,而是或许成为了一个经过处理的代理bean,可能通过cglib生成的,也可以是其他技术生成的。
返回非空:返回值是Object类型,这意味着我们可以返回任何类型的值,由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成对象的目标对象的实例,也就是说,如果返回了非空的值,那么以后我们需要用到这个bean的时候,拿到的就现在返回的对象了,也就不会去走第二步去实例化对象了;
返回空(null)值:默认也是返回null值的,那么就直接返回,接下来会调用doCreateBean方法来实例化对象;
BeanPostProcessor
BeanPostProcessor是容器提供给我们的一个扩展接口,也称Bean的后置处理器。我们可以实现该接口,用来添加业务中特有的逻辑。
BeanPostProcessor实现类也是一个普通的Bean,那么Spring是怎么保证BeanPostProcessor实现类在开发人员写的Bean之前加载的呢?
这就要回到我们最熟悉org.springframework.context.support.AbstractApplicationContext#refresh方法中
public void refresh() {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
其中registerBeanPostProcessors方法就会对BeanPostProcessor进行注册,在finishBeanFactoryInitialization中再完成非懒加载的单例Bean的加载。
从而BeanPostProcessor就会在业务Bean之前加载,因此可以在业务Bean实例化前进行调用。
2、实例化对象 instantiateBean
doCreateBean方法创建实例,用反射技术创建,这个没什么好说的,只是相当于new了一个对象出来而已,但需要注意的是,这个时候只是将对象实例化了,对象内的属性还未设置;
现在可以进入doCreateBean中,createBeanInstance包含了实例化bean并封装为BeanWrapper的逻辑,且内部提供了多种实例化的方式。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
//将bean转化为class对象
Class<?> beanClass = resolveBeanClass(mbd, beanName);
//基于Supplier实例化
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
//基于工厂方法实例化
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
//省略部分代码
//基于有参构造函数实例化
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
//基于无参构造函数实例化
return instantiateBean(beanName, mbd);
}
protected Object doCreateBean(final String beanName,final RootBeanDefinition mbd,final Object[] args)
createBeanInstance 方法// 根据指定bean使用对应的策略创建新的实例,如:工厂模式、构造函数自动注入、简单初始化等
// 是否提早曝光:单例&允许循环依赖&当前bean是否在创建中,检测循环依赖
// 为了避免后期循环依赖,可以在bean初始化完成钱将创建实例的ObjectFactory加入工厂
// 对bean在一次依赖引用,主要应用SmartInstantiationAwareBeanPostProcessor,其中我们熟知的AOP就是在这里将advice动态织入bean中,如没有则直接返回
// 对bean属性填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性,则会递归初始化依赖bean
// 调用初始化方法,比如init-method
// earlySingletonReference只检测到有循环依赖的情况下才不会为空
// 如果exposeObject没有在初始化方法中被改变,也就是没有增强
// 检测依赖
// 因为bean创建其所依赖的bean一定是已经创建了,actualDependentBeans不为空则表示当前bean却没有没全部创建完,也就是说存在循环依赖
// 根据scope注册bean
}
3、实例化后置
方法名称: InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(Object bean, String beanName)
在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为他的返回值是决定要不要调用postProcessPropertyValues方法中的一个因素(因为还有一个因素是mbd.getDependencyCheck());
实例化后的后处理器的应用:
在讲解从缓存中获取单例bean的时候提到过,Spring中的规则是在bean的初始化后尽可能保证将注册的后处理器的postProcessAfterInitialization方法应用到该bean中,因为如果返回的bean不为空,那么便不会再次经历普通bean的创建过程,所以只能在这里应用后处理器的postProcessAfterInitialization方法。
返回false :如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;
返回true : 如果返回true,postProcessPropertyValues就会被执行
4、属性修改
方法名称 :InstantiationAwareBeanPostProcessor.PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
此方法可对属性值进行修改,修改范围包括添加、修改、删除操作;,如果实例化后置 postProcessAfterInstantiation() 方法返回false,那么该方法不会被调用;
5、给用户属性赋值
用户属性指的是用spring 自定义的bean对象属性,像 User、Student、Teacher 、UserService、IndexService 这类的对象都是自定义bean对象,第5步主要给这类属性进行赋值操作,使用的是 AbstractAutowireCapableBeanFactory.populateBean() 方法进行赋值;
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//如果属于InstantiationAwareBeanPostProcessor类型,则调用postProcessAfterInstantiation
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
//一旦任意一个InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation返回false,属性注入阶段将不再进行,直接进入下一个阶段
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);
//按照名称注入
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
//按照类型注入
if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//省略掉InstantiationAwareBeanPostProcessor其他两个扩展点及下面的依赖检查
if (pvs != null) {
//属性注入
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
6、给容器属性赋值
容器属性其实就是容器自带的属性,这些属性都是spring本来就有的;可以肯定的是,它们都是 Aware 接口的实现类,主要有以下实现类,我已经将它们的执行顺序都排列好了:
至于实现Aware接口可以做哪些事情拓展Spring功能或利用Spring容器环境属性。可以自行了解 ,如ApplicationContextAware接口的作用_RichardGeek的博客-优快云博客
从doCreateBean内的initializeBean开始(下面的7/8/9/10/11/12过程)
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//1.设置Aware相关依赖
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
//2.调用BeanPostProcessor的前置处理
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//3.1调用InitializingBean的afterPropertiesSet方法
//3.2调用自定义的init method方法
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
//4.调用BeanPostProcessor的后置处理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
设置Aware相关依赖
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
//如果bean实现了BeanNameAware接口,则设置BeanName
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
//如果bean实现了BeanClassLoaderAware接口,则设置BeanClassLoader
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
//如果bean实现了BeanFactoryAware接口,则设置BeanFactory
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
调用BeanPostProcessor的前置处理
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//获取所有BeanPostProcessor的实现类
for (BeanPostProcessor processor : getBeanPostProcessors()) {
//挨个调用postProcessBeforeInitialization方法
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
这一步会获取容器中所有BeanPostProcessor的实现类,挨个调用postProcessBeforeInitialization方法。在其返回不为null的情况下,后一个结果会覆盖上一个结果。
当然在处理到ApplicationContextAwareProcessor的时候,会设置以下Aware依赖。
- EnvironmentAware
- EmbeddedValueResolverAware
- ResourceLoaderAware
- ApplicationEventPublisherAware
- MessageSourceAware
- ApplicationContextAware
在处理到InitDestroyAnnotationBeanPostProcessor,会找出被@PostConstruct注解修饰的方法,并执行。
invokeInitMethods
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
//如果实现了InitializingBean接口,则调用afterPropertiesSet方法
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
//调用xml中声明的init-method指定的方法
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
调用BeanPostProcessor的后置处理
和前置处理类似,只是调用postProcessAfterInitialization方法,不再赘述。
因此,初始化过程又可以被细分为
7、Bean初始化前置
方法名称: BeanPostProcessor.postProcessBeforeInitialization()
在每一个 Bean 初始化之前执行的方法(有多少 Bean 调用多少次)
注意 : 启用同时实现了BeanPostProcessor接口且标注了@PostConstruct注解的方法会失效
当前类同时实现了BeanPostProcessor接口启用BeanPostProcessor#postProcessBeforeInitialization该方法后,同时该类内部又有方法使用了@PostConstruct,该类的@PostConstruct会失效。
8、Bean初始化后置
方法名称: BeanPostProcessor.postProcessAfterInitialization()
在每一个 Bean 初始化之后执行的方法(有多少 Bean 调用多少次)
初始化前置和初始化后置的实现代码如下
@Component
public class ExtBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 在每一个 Bean 初始化之前执行的方法(有多少 Bean 调用多少次)
// 注意 : 启用该方法后,标注了@PostConstruct注解的方法会失效
System.out.println("初始化前置方法");
return null;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
在每一个 Bean 初始化之后执行的方法(有多少 Bean 调用多少次)
System.out.println("初始化后置方法");
return null;
}
}
9、执行初始化方法
初始化方法有三个,分别是 添加了@PostConstruct 注解的方法、实现InitializingBean接口、在@bean注解上添加 initMethod属性;
10、初始化方法一:@PostConstruct
在bean对象内添加@PostConstruct 注解后即可实现初始化的功能,被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。 有多个则会执行多次;
注意: 如果spring 实现了 BeanPostProcessor接口的postProcessBeforeInitialization() 方法,也就是12的初始后置方法,那么@PostConstruct注解会失效;
// @PostConstruct注解
@Component
public class ExtPostConstruct {
/**
* 被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。如果有多个则会执行多次
* 注意: 如果spring 实现了 BeanPostProcessor接口的postProcessBeforeInitialization方法,该@PostConstruct注解会失效
*/
@PostConstruct
public void init() {
System.out.println("第一个init...");
}
// 有多个会执行多次
@PostConstruct
public void init1() {
System.out.println("第二个init1...");
}
}
11、InitializingBean.afterPropertiesSet()
spring 初始化方法之一,作用是在BeanFactory完成属性设置之后,执行自定义的初始化行为。
执行顺序:在initMethod之前执行,在@PostConstruct之后执行。
@Component
public class ExtInitializingBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
// 一个 InitializingBean 执行一次
// spring 初始化方法,作用是在BeanFactory完成属性设置之后,执行自定义的 初始化行为.
// 执行顺序:在initMethod之前执行,在@PostConstruct之后执行
System.out.println("InitializingBean");
}
}
12、init-method
bean 配置文件属性 init-method 用于在bean初始化时指定执行方法,用来替代继承 InitializingBean接口,
注意的一点是只有一个类完整的实例被创建出来后,才能走初始化方法。
@Component
public class InitMethod {
// 在@Bean注解上添加initMethod属性,指向类中的 initMethod_1 执行初始化方法
@Bean(initMethod = "initMethod_1")
public BeanTest getBeanTest(){
return new BeanTest();
}
}
13、使用中
到这一步,bean对象就已经完全创建好了,是一个完整对象了,并且正在被其他对象使用了;
14、销毁流程
在容器关闭的时候,会进入Bean的销毁阶段,代码从AbstractApplicationContext的close()方法开始。
不急着进入close()方法,先看一下第一节代码中最末尾的方法:
protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
//如果Bean不是多例且需要在容器关闭时销毁
if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
if (mbd.isSingleton()) {
//给当前Bean绑定一个DisposableBeanAdapter
registerDisposableBean(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
else {
// A bean with a custom scope...
Scope scope = this.scopes.get(mbd.getScope());
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
}
scope.registerDestructionCallback(beanName,
new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
}
}
}
public void registerDisposableBean(String beanName, DisposableBean bean) {
synchronized (this.disposableBeans) {
this.disposableBeans.put(beanName, bean);
}
}
在registerDisposableBeanIfNecessary中,会对每一个需要在容器关闭时进行销毁的单例Bean,绑定对应的DisposableBeanAdapter对象。最后把这些Bean及其DisposableBeanAdapter放入进名称为disposableBeans的map中,以供后续使用。
现在我们进入AbstractApplicationContext的close()方法,一路上兜兜转转,会进入到DefaultSingletonBeanRegistry的destroySingletons方法中。
public void destroySingletons() {
String[] disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
destroySingleton(disposableBeanNames[i]);
}
//省略部分代码
}
先拿到所有待销毁Bean的名称,挨个调用destroySingleton方法,一直往下走,最终会进入到DefaultSingletonBeanRegistry的destroyBean中
其中核心的一句
// Actually destroy the bean now...
bean.destroy();
按照beanName从disposableBeans中获取到bean对应的DisposableBeanAdapter,调用其destroy方法:
public void destroy() {
//调用被@PreDestroy注解修饰的方法
//具体可以跟进InitDestroyAnnotationBeanPostProcessor类
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
//如果实现了DisposableBean接口,则调用destroy方法
if (this.invokeDisposableBean) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((DisposableBean) this.bean).destroy();
return null;
}, this.acc);
} else {
((DisposableBean) this.bean).destroy();
}
}
//调用xml中自定义的destroy-method方法
if (this.destroyMethod != null) {
invokeCustomDestroyMethod(this.destroyMethod);
} else if (this.destroyMethodName != null) {
Method methodToCall = determineDestroyMethod(this.destroyMethodName);
if (methodToCall != null) {
invokeCustomDestroyMethod(methodToCall);
}
}
}
到这里,Bean的销毁过程基本就结束了,我们使用一张图来概括下:
14.1 DisposableBean.destroy()。单例模式的销毁方式,示例代码
/**
* 销毁方法
*/
@Component
public class ExtDisposableBean implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("我被销毁了");
}
}
14.2 destory-method方法
还是拿 第11 个流程的例子来讲,只不过这次我们在@Bean注解里加上 destroyMethod属性,指向销毁方法 :destroyMethod_1()
@Component
public class InitMethod {
// 在@Bean注解上添加initMethod属性,指向类中的 initMethod_1 执行初始化方法
// 在@Bean注解上添加destroyMethod属性,指向类中的 destroyMethod_1 执行销毁方法
@Bean(initMethod = "initMethod_1",destroyMethod = "destroyMethod_1")
public BeanTest getBeanTest(){
return new BeanTest();
}
}
BeanTest.java
package com.Spring.Boot.init.bean;
public class BeanTest {
// 将要执行的初始化方法
public void initMethod_1(){
System.out.println("我是beanTest的init方法");
}
// 将要执行的销毁方法
public void destroyMethod_1(){
System.out.println("我是beanTest的init方法");
}
}
总结
我们整个阶段串联起来,Spring的Bean生命周期的大体全流程如下图:
流程技巧: 先记住5个大阶段,实例化、属性赋值、初始化、正常使用过程与销毁。
在生命周期内部,可以自定义Bean后置处理器以及实现接口的形式来进行扩展
- 容器级的扩展点,InstantiationAwareBeanPostProcessor与BeanPostProcessor。
- Bean级的扩展点,Aware相关接口,InitializingBean与DisposableBean。
此外,可以使用注解或xml配置形式,指定扩展点
- @PostConstruct注解
- @PreDestroy注解
- xml中init-method
- xml中destroy-method
那么再记忆生命周期的先后顺序,就会容易很多:
getBean
- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
- 实例化
- InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation
- 属性赋值
- Aware接口回调
- BeanPostProcessor.postProcessBeforeInitialization
- @PostConstruct指定的方法
- InitializingBean.afterPropertiesSet
- xml中init-method指定的方法
- BeanPostProcessor.postProcessAfterInitialization
关闭容器后
- @PreDestroy指定的方法
- DisposableBean.destroy
- xml中destroy-method指定的方法