spring bean扩展点:后处理器 BeanPostProcessor

目录

一、BeanPostProcessor

1.1. 什么是 BeanPostProcessor

1.2. BeanPostProcessor 的种类

1.3. BeanPostProcessor 的注册

二、自定义后置处理器演示

三、源码中的调用场景

3.1、InstantiationAwareBeanPostProcessor 后置处理器

3.1.1、postProcessBeforeInstantiation方法

3.1.2、postProcessAfterInstantiation方法

3.1.3、postProcessPropertyValues方法

3.1.4、总结

3.2、SmartInstantiationAwareBeanPostProcessor

3.2.1、determineCandidateConstructors方法

3.2.2、getEarlyBeanReference

3.3、BeanPostProcessor

3.3.1、postProcessBeforeInitialization方法

3.3.2、postProcessAfterInitialization方法

3.3.3、总结

四、总结

 


经过前面的文章介绍,我们了解的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 属性填充阶段

通过代码我们可以比较清楚的看到整体逻辑:

  1. 若InstantiationAwareBeanPostProcessor .postProcessAfterInstantiation 返回true,才会执行下面步骤
  2. 调用InstantiationAwareBeanPostProcessor .postProcessProperties 注入属性,
  3. 若InstantiationAwareBeanPostProcessor .postProcessProperties 返回为null,才会执行下面步骤
  4. 调用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方法来生成实例;

四、总结

最后,附一张自己画的调用流程图,由于完全有本人自己阅读绘制,可能会出现些许纰漏,如果发现,麻烦指正,谢谢。

 

 

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值