spring bean扩展点:后处理器 BeanPostProcessor

本文详细解读了BeanPostProcessor接口及其子接口(如InstantiationAwareBeanPostProcessor)在Spring框架中的作用,包括后置处理器的注册、自定义实现和源码中的调用场景。重点介绍了postProcessBeforeInstantiation、postProcessAfterInstantiation和相关方法的使用,以及SmartInstantiationAwareBeanPostProcessor在实例化预测和循环依赖解决中的应用。

目录

一、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方法来生成实例;

四、总结

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

 

 

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值