目录
3.1、InstantiationAwareBeanPostProcessor 后置处理器
3.1.1、postProcessBeforeInstantiation方法
3.1.2、postProcessAfterInstantiation方法
3.1.3、postProcessPropertyValues方法
3.2、SmartInstantiationAwareBeanPostProcessor
3.2.1、determineCandidateConstructors方法
3.3.1、postProcessBeforeInitialization方法
3.3.2、postProcessAfterInitialization方法
经过前面的文章介绍,我们了解的sping bean生命周期,在其中伴随着大量的后置处理器的使用。为了弄清楚Spring框架,我们需要分别弄清楚相关核心接口的作用,本文来介绍下BeanPostProcessor接口。
一、BeanPostProcessor
所谓的 BeanPostProcessor
翻译过来就是Bean后处理器。作用是在Bean对象在实例化和依赖注入完毕后,在显示调用初始化方法的前后添加我们自己的逻辑。注意是Bean实例化完毕后及依赖注入完成后触发的。
1.1. 什么是 BeanPostProcessor
BeanPostProcessor
是 Spring提供给我们的一个非常重要的扩展接口,并且Spring内部的很多功能也是通过 BeanPostProcessor 来完成的(目前看到最典型的就是 AnnotationAwareAspectJAutoProxyCreator
的 注入)。
1.2. BeanPostProcessor 的种类
BeanPostProcessor
在Spring 中的子类非常多(idea 显是有46个),比如
InstantiationAwareBeanPostProcessor
: 在Spring 的bean加载过程中起了非常重要的作用,主要作用于bean实例化前后阶段。
其中的方法:
postProcessBeforeInstantiation():在bean实例化前回调,返回实例则不对bean实例化,返回null则进行spring bean实例化(doCreateBean);
postProcessAfterInstantiation():在bean实例化后在填充bean属性之前回调,返回true则进行下一步的属性填充,返回false:则不进行属性填充
postProcessProperties:在属性赋值前的回调在applyPropertyValues之前操作可以对属性添加或修改等操作最后在通过applyPropertyValues应用bean对应的wapper对象
- SmartInstantiationAwareBeanPostProcessor :这个也是作用于bean实例化阶段。
determineCandidateConstructors(): 实例化阶段,推断实例化构造方法
getEarlyBeanReference() : 在实例化之后提前暴露一个ObjectFactory,解决循环依赖问题
- MergedBeanDefinitionPostProcessor :处理合并父子 BeanDefinition 后其中的属性
InstantiationAwareBeanPostProcessorAdapter
: 在Spring 的bean加载过程中起了非常重要的作用AnnotationAwareAspectJAutoProxyCreator
: bean 创建过程中的 属性注入时起作用AspectJAwareAdvisorAutoProxyCreator
: Aspect 的 AOP 功能实现也全仰仗BeanPostProcessor 的特性。
1.3. BeanPostProcessor 的注册
BeanPostProcessor 的注册是在 AbstractApplicationContext#registerBeanPostProcessors 中完成的。在Spring 刚刚启动时候,会调用refresh() 方法,随机调用registerBeanPostProcessors 方法。 在这个方法中,Spring 将各处的BeanPostProcessor 的实现类 注册到 BeanFactory.beanPostProcessors 属性中,后面获取BeanPostProcessor 时直接通过该属性获取。
二、自定义后置处理器演示
日常使用中,我们一般编写一个类来实现 BeanPostProcessor
或者 InstantiationAwareBeanPostProcessor
接口,根据每个方法的调用时机,来完成响应的工作。
下面介绍一下接口方法,这里通过 InstantiationAwareBeanPostProcessor
接口来介绍 。InstantiationAwareBeanPostProcessor
是 BeanPostProcessor
的子接口,在 BeanPostProcessor
基础上又扩展了三个方法。
/**
* 自定义
*
* @Author: dukun0210
* @Date: 2021/2/23 14:46
*/
@Component
public class DemoPostProcesser implements InstantiationAwareBeanPostProcessor {
/**
* 这个在实例化前执行
* 此时bean还没创建,可以通过这方法代替 Spring 容器创建的方法
* InstantiationAwareBeanPostProcessor 提供的方法, 在 Class<T> -> T 的转换过程中
* @param beanClass
* @param beanName
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("DemoPostProcesser.postProcessBeforeInstantiation ### 1");
return null;
}
/**
* 实例化后,填充属性前
* 如果返回true,则会调用postProcessProperties和postProcessPropertyValues 来注入属性
* 此时bean已经创建,属性尚未注入
* InstantiationAwareBeanPostProcessor 提供的方法, 返回的值代表是否需要继续注入属性,
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("DemoPostProcesser.postProcessAfterInstantiation ### 2");
return true;
}
/**
* 填充属性前
* InstantiationAwareBeanPostProcessor 提供的方法,可以在这个方法中进行bean属性的注入,Aop 就是在此方法中进行了代理的创建
* 只有postProcessAfterInstantiation 返回true 时才会调用
* @param pvs
* @param bean
* @param beanName
* @return
* @throws BeansException
*/
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
System.out.println("DemoPostProcesser.postProcessProperties ### 3");
return pvs;
}
//InstantiationAwareBeanPostProcessor 提供的方法,可以在这个方法中进行bean属性的注入, 这个方法已经过时,使用postProcessProperties 代理
// 只有postProcessAfterInstantiation 返回true 时 且 postProcessProperties 返回 null 时调用
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
System.out.println("DemoPostProcesser.postProcessPropertyValues ### 4");
return pvs;
}
// BeanPostProcessor 提供的方法,在bean初始化前调用,这时候的bean大体已经创建完成了,在完成一些其他属性的注入
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("DemoPostProcesser.postProcessBeforeInitialization ### 5");
return bean;
}
// BeanPostProcessor 提供的方法,在bean初始化后调用,这时候的bean 已经创建完成了
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("DemoPostProcesser.postProcessAfterInitialization ### 6");
return bean;
}
}
其调用顺序也和标注相同:
注意:
这里可以看到 postProcessPropertyValues
方法并没有调用,因为对于一个 过时的方法 没必要必须要调用它,前面也提到 postProcessAfterInstantiation
返回true 并且 postProcessProperties
返回不为null 才会调用该方法,这里postProcessProperties
返回不为null ,所以不会调用postProcessPropertyValues
方法。
三、源码中的调用场景
下面为了方便描述,进行一些简化写法,为了后面描述方便。在spring bean生命周期中主要是依赖下面的接口
BP : BeanPostProcessor
IBP : InstantiationAwareBeanPostProcessor
SBP : SmartInstantiationAwareBeanPostProcessor
其结构如下图:
这里就不具体贴出多少代码。简单解释一下调用场景
Spring 在启动过程中,会将所有实现了 BeanPostProcessor 接口的子类保存到 AbstractBeanFactory 中的 beanPostProcessors 集合中,如下:
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();
在适当的时候(这个适当的时候就根据 每个接口方法定义的意义来判断), Spring会获取 所有的BeanPostProcessor 子类集合,即 beanPostProcessors ,经过类型过滤后,调用对应的方法。比如,就是对 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation
方法的调用流程(其余方法的调用也类似):
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 因为只有 InstantiationAwareBeanPostProcessor 类型才有postProcessBeforeInstantiation 方法,所以这里要判断一下是不是 InstantiationAwareBeanPostProcessor 类型
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
3.1、InstantiationAwareBeanPostProcessor 后置处理器
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
}
下面来介绍在 Spring 创建流程中 每个方法的实际调用位置:
3.1.1、postProcessBeforeInstantiation方法
路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation(beanName, mbdToUse)
下面是执行时机:
//如果Bean配置了初始化前和初始化后的处理器,则试图返回一个需要创建Bean的代理对象
//TODO 第一次调用bean的后置处理器 主要判断bean需要被代理 bean一般都为空
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
//如果beforeInstantiationResolved还没有设置或者是false(说明还没有需要在实例化前执行的操作)
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// 判断是否有注册过InstantiationAwareBeanPostProcessor类型的bean
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//执行
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
方法在 Bean 创建 之前调用,我所理解的目的是替换Spring 容器创建bean, 当
IBP.postProcessBeforeInstantiation
返回不为null时,则不会再通过Spring 创建bean,而是使用IBP.postProcessBeforeInstantiation
返回的bean
spring的内置实现返回的都是null
实现类 AbstractAutoProxyCreator#postProcessBeforeInstantiation:主要作用是判断 bean是否需要被代理 ,需要被代理的类 就放入map中
/**
* 判断类是否需要被代理
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return
* @throws BeansException
*/
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
//advisedBeans 不需要被代理的对象
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
3.1.2、postProcessAfterInstantiation方法
在
AbstractAutowireCapableBeanFactory#populateBean
方法中,此时bean已经创建完成,正在进行属性注入。而postProcessAfterInstantiation
的返回值决定是否继续注入
路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean(beanName, mbd, instanceWrapper)
// 调用 postProcessAfterInstantiation 方法吗,如果返回false,直接return;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
3.1.3、postProcessPropertyValues方法
这里通过 InstantiationAwareBeanPostProcessor
#postProcessPropertyValues
方法完成了属性的注入分析。
路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean(beanName, mbd, instanceWrapper)。
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
//TODO 获取的bean的后置处理器
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
//
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
主要实现类有2个:
1、AutowiredAnnotationBeanPostProcessor #
postProcessPropertyValues
中的实现类 处理 @Autowired 注解和@Value 注解的自动注入功能。2、CommonAnnotationBeanPostProcessor#
postProcessPropertyValues
中的实现类 处理 @Resource注解、@PostConstruct等通用注解。
这里就不分析了。在这篇文章里有分析 spring bean生命周期三---Spring Bean populateBean 属性填充阶段
通过代码我们可以比较清楚的看到整体逻辑:
- 若InstantiationAwareBeanPostProcessor
.postProcessAfterInstantiation
返回true,才会执行下面步骤 - 调用InstantiationAwareBeanPostProcessor
.postProcessProperties
注入属性, - 若InstantiationAwareBeanPostProcessor
.postProcessProperties
返回为null,才会执行下面步骤 - 调用InstantiationAwareBeanPostProcessor
.postProcessPropertyValues
注入属性。
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
...
// 调用 postProcessAfterInstantiation 方法吗,如果返回false,直接return;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
}
...
if (hasInstAwareBpps) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 调用 postProcessProperties 注入属性
PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
if (filteredPds == null) {
filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
}
// 调用 postProcessPropertyValues 注入属性
pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvsToUse == null) {
return;
}
}
pvs = pvsToUse;
}
}
}
...
}
3.1.4、总结
- InstantiationAwareBeanPostProcessor接口继承BeanPostProcessor接口,它内部提供了3个方法,再加上BeanPostProcessor接口内部的2个方法,所以实现这个接口需要实现5个方法。InstantiationAwareBeanPostProcessor接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置
- postProcessBeforeInstantiation方法是最先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走
- postProcessAfterInstantiation方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返回true,postProcessPropertyValues就会被执行
- postProcessPropertyValues方法对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)。如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用。可以在该方法内对属性值进行修改
- 父接口BeanPostProcessor的2个方法postProcessBeforeInitialization和postProcessAfterInitialization都是在目标对象被实例化之后,并且属性也被设置之后调用的
- Instantiation表示实例化,Initialization表示初始化。实例化的意思在对象还未生成,初始化的意思在对象已经生成。
3.2、SmartInstantiationAwareBeanPostProcessor
SmartInstantiationAwareBeanPostProcessor 继承自 InstantiationAwareBeanPostProcessor;但是SmartInstantiationAwareBeanPostProcessor多了一个三个方法
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
// 预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null
Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException;
// 选择合适的构造器,比如目标对象有多个构造器,在这里可以进行一些定制化,选择合适的构造器
// beanClass参数表示目标实例的类型,beanName是目标实例在Spring容器中的name
// 返回值是个构造器数组,如果返回null,会执行下一个PostProcessor的determineCandidateConstructors方法;否则选取该PostProcessor选择的构造器
Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException;
// 获得提前暴露的bean引用。主要用于解决循环引用的问题
// 只有单例对象才会调用此方法
Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;
}
3.2.1、determineCandidateConstructors方法
检测Bean的构造器,可以检测出多个候选构造器,再有相应的策略决定使用哪一个来实例化 bean,如AutowiredAnnotationBeanPostProcessor实现将自动扫描通过@Autowired/@Value注解的构造器从而可以完成构造器注入。
路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance(beanName, mbd, args)。
实现类:AutowiredAnnotationBeanPostProcessor #determineCandidateConstructors。
// Need to determine the constructor...
//TODO 第二次调用后置处理器推断构造方法 下面是单例对象的 使用Bean的构造方法进行实例化
//找到 class 构造方法 特殊的算法
/* TODO spring 通过构造方法实例化 bean的原理
实例化这个对象---首先要推断构造方法
这个分两种类型
1、手动注入
会在后置处理器中 找到实现 SmartInstantiationAwareBeanPostProcessor接口的类型
AutowiredAnnotationBeanPostProcessor类中的determineCandidateConstructors 方法来推断出
合适的构造方法创建对象
1.1、只有一个无参构造方法 ctors为 null 使用默认无参构造方法
1.2 如果有多个构造方法 ctors为 null 使用默认无参构造方法
1.3 如果只有一个有参构造方法 ctors不为null 因为只有一个有参数的 只能用这个了
1.4、多个构造方法 且只有一个构造方法加了@Autowired(required = true) 用这个构造方法来创建对象
1.5、多个构造方法 且多个构造方法加了@Autowired(required = true) spring ioc容器报错
1.6、多个构造方法 且多个构造方法加了@Autowired(required = false) 就把构造方法都加到集合中 第二次推断
2、自动注入 --通过构造方法自动注入
2.1、如果有多个构造方法 找出最优的构造器 参数最多的 为最优的
*/
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR || //这个表示自动装配
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//使用容器的自动装配特性,调用匹配的构造方法实例化
//使用推断出来的构造方法找到一个可以用的 实例化bean
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
//使用默认的无参构造方法实例化
return instantiateBean(beanName, mbd);
3.2.2、getEarlyBeanReference
这个方法见名思意就是获取提前引用的意思了,Spring中解决循环引用的时候有调用这个方法。
在 Spring 解决循环依赖时候使用,返回的值将作为ObjectFactory 的 保存的Object,用于循环依赖的提前暴露。
重点 解决循环依赖 提前暴露的是一个ObjectFactory工厂 而不是一个对象
//TODO 第四调用后置处理器
// 重点 解决循环依赖 提前暴露的是一个工厂 而不是一个对象
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
路径:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference(beanName, mbd, bean)。
实现类:AbstractAutoProxyCreator #getEarlyBeanReference
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// getEarlyBeanReference 的返回值作为 ObjectFactory 的返回值保存到singletonFactories缓存中
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
1、加载circulationa,然后将调用了代码,提前将singleto暴露出去,但是这个时候只是getEarlyBeanReference还没有被调用;因为没有出现循环引用的情况;现在放入缓存是为了预防有循环引用的情况可以通过这个getEarlyBeanReference获取对象;
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
2.然后填充属性值;调用下面的方法,在填充属性的时候发现引用了circulationb;然后就去获取circulationb来填充
populateBean(beanName, mbd, instanceWrapper);
3.加载circulationb, 执行的操作跟 1,2一样; circulationb发现了引用了circulationa;然后直接调用getSingleton获取circulationa;
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
//这个地方就是调用getEarlyBeanReference的地方了;
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
这一步返回的就是 getEarlyBeanReference得到的值;
4.执行getEarlyBeanReference方法
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
if (exposedObject == null) {
return null;
}
}
}
}
return exposedObject;
}
4.1 一般情况下,如果系统中没有SmartInstantiationAwareBeanPostProcessor接口;就是直接返回exposedObject什么也不做;
4.2.所以利用SmartInstantiationAwareBeanPostProcessor可以改变一下提前暴露的对象;
5.拿到引用了之后…就不分析了…。
3.3、BeanPostProcessor
我们看下BeanPostProcessors的接口
public interface BeanPostProcessor {
//在初始化之前调用
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//在初始化之后调用
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
我们来看下BeanPostProcessors的接口在bean生命周期中执行时间
postProcessBeforeInitialization
调用时机是bean已经创建完成,但是尚未初始化执行。postProcessAfterInitialization是在bean完成初始后后执行。
如果这个接口的某个实现类被注册到某个容器,那么该容器的每个Bean在调用初始化方法之前,都会获得该接口实现类的一个回调。容器调用接口定义的方法时会将该受管Bean的实例和名字通过参数传入方法,进过处理后通过方法的返回值返回给容器。也就是回调了***postProcessBeforeInitialization*** 方法
要使用BeanPostProcessor回调,就必须先在容器中注册实现该接口的类,那么如何注册呢?BeanFactory和ApplicationContext容器的注册方式不大一样:若使用BeanFactory,则必须要显示的调用其addBeanPostProcessor()方法进行注册,参数为BeanPostProcessor实现类的实例;如果是使用ApplicationContext,那么容器会在配置文件在中自动寻找实现了BeanPostProcessor接口的Bean,然后自动注册,我们要做的只是配置一个BeanPostProcessor实现类的Bean就可以了。
3.3.1、postProcessBeforeInitialization方法
postProcessBeforeInitialization
调用时机是bean已经创建完成,但是尚未初始化,即一些属性配置尚未完成(我看到的就一个 init-method 的配置)。使用场景也只有一处,即AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)
。
程序走到这里,代表 resolveBeforeInstantiation
方法 中的 postProcessBeforeInstantiation
并未代理 bean的创建,在这里则是由Spring 创建的bean的时候来调用。
代码如下:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
....
// 调用 BP.postProcessBeforeInitialization
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 初始化属性,貌似就初始化了 一个 init-method
...
if (mbd == null || !mbd.isSynthetic()) {
// 调用 BP.postProcessAfterInitialization
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
3.3.2、postProcessAfterInitialization方法
BP.postProcessAfterInstantiation
的调用都被封装到 AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
方法中。
而applyBeanPostProcessorsAfterInitialization
方法的调用
applyBeanPostProcessorsAfterInitialization
方法在下面三个方法中调用:
- AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation
- AbstractAutowireCapableBeanFactory#initializeBean(String, Object, RootBeanDefinition)
- AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean
3.3.3、总结
1.BeanPostProcessors注册发生在容器启动的时候;自动注册BeanPostProcessors类型;
2.只要调用getBean初始化对象都会触发BeanPostProcessors接口的两个方法,并且是所有BeanPostProcessors实例都会触发;
3.如果是FactoryBean类型,容器不会帮我们自动初始化它产生的实例
除非是SmartFactoryBean实例,并且它的isEagerInit()返回的是true;IOC容器才会也帮我们调用它的getObject方法来生成实例;
四、总结
最后,附一张自己画的调用流程图,由于完全有本人自己阅读绘制,可能会出现些许纰漏,如果发现,麻烦指正,谢谢。