Skip to content

注册 BeanPostProcessor 后置处理器

BeanPostProcessor

Spring 核心方法中 registerBeanPostProcessors(beanFactory);

BeanPostProcessor 后置处理器的注册。此方法就是把实现 BeanPostProcessor 接口的类,提前实例化,这个接口类里面有两个方法,可以进行相应的操作。

bean 实例化前的操作,以及 bean 实例化后的操作,这个实例化在其他正常的实例化方法之前,比如可以阻止其他 bean 的 IOC 依赖注入。

把实现了 BeanPostProcessor 接口的类实例化,并且加入 到 BeanFactory 中。

获取到实例化的 bean 对象,可以对其属性值等做修改操作。 比如,拿到 bean 对象,可以判断其类上有没有特定的注解等,根据自己的条件,可以创建一个代理对象,然后返回,这样就对每个 bean 做了这样的后置增强处理。

java
public interface BeanPostProcessor {
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}
}

在哪儿调用的这两个方法?

是在 Spring 完成 bean 实例化和依赖注入后,调用后置处理器的。

├─finishBeanFactoryInitialization(beanFactory); Spring 核心方法中的
│ ├─beanFactory.preInstantiateSingletons();
│ │ ├─getBean(beanName);
│ │ │ ├─doGetBean(name, null, null, false);
│ │ │ │ ├─if (mbd.isSingleton()) {
│ │ │ │ │ ├─下面的 getSingleton 方法传入了一个 Lambda 表达式,并在 getSingleton 中调用了传入的 lambda 表达式,创建了 bean 实例。
│ │ │ │ │ ├─sharedInstance = getSingleton(beanName, () -> {
│ │ │ │ │ │ ├─return createBean(beanName, mbd, args);
│ │ │ │ │ │ │ ├─Object beanInstance = doCreateBean(beanName, mbdToUse, args);
│ │ │ │ │ │ │ │ ├─instanceWrapper = createBeanInstance(beanName, mbd, args);
│ │ │ │ │ │ │ │ ├─下面是依赖注入的核心方法(非常重要)
│ │ │ │ │ │ │ │ ├─populateBean(beanName, mbd, instanceWrapper);
│ │ │ │ │ │ │ │ ├─下面是依赖注入完成后的调用(非常重要)
│ │ │ │ │ │ │ │ ├─exposedObject = initializeBean(beanName, exposedObject, mbd);
│ │ │ │ │ │ │ │ │ ├─这里调用 before 方法
│ │ │ │ │ │ │ │ │ ├─wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
│ │ │ │ │ │ │ │ │ ├─invokeInitMethods(beanName, wrappedBean, mbd);
│ │ │ │ │ │ │ │ │ ├─这里调用 after 方法,就是这里完成了 AOP 代理功能
│ │ │ │ │ │ │ │ │ ├─wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

常见的子类

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor 继承自 BeanPostProcessor 接口。主要多提供了以下三个方法:

  • postProcessBeforeInstantiation:该方法是在 Bean 实例化目标对象之前调用,返回的 Bean 对象可以代理目标,从而有效的阻止了目标 Bean 的默认实例化。
  • postProcessAfterInstantiation:该方法执行在通过构造函数或工厂方法在实例化 bean 之后但在发生 Spring 属性填充(通过显式属性或自动装配)之前执行操作。这是在 Spring 的自动装配开始之前对给定的 bean 实例执行自定义字段注入的理想回调。如果该方法返回 false,那么它会阻断后续 InstantiationAwareBeanPostProcessor 后置处理器的执行,并且会阻止后续属性填充的执行逻辑。
  • postProcessPropertyValues:在工厂将给定属性值应用于给定 bean 之前,对它们进行后处理。允许检查是否满足所有依赖关系,例如基于 bean 属性设置器上的“ Required”注解。还允许替换要应用的属性值,通常是通过基于原始 PropertyValues 创建新的 MutablePropertyValues 实例,添加或删除特定值来实现。

这个接口是在哪儿调用的?

├─finishBeanFactoryInitialization(beanFactory); Spring 核心方法中的
│ ├─beanFactory.preInstantiateSingletons();
│ │ ├─getBean(beanName);
│ │ │ ├─doGetBean(name, null, null, false);
│ │ │ │ ├─if (mbd.isSingleton()) {
│ │ │ │ │ ├─下面的 getSingleton 方法传入了一个 Lambda 表达式,并在 getSingleton 中调用了传入的 lambda 表达式,创建了 bean 实例。
│ │ │ │ │ ├─sharedInstance = getSingleton(beanName, () -> {
│ │ │ │ │ │ ├─return createBean(beanName, mbd, args);
│ │ │ │ │ │ │ ├─Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
java
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // Make sure bean class is actually resolved at this point.
        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;
}
  • TargetSource 接口的运用,可以在用改一个类实现该接口,然后在里面定义实例化对象的方式,然后返回
  • 也就是说不需要 spring 帮助我们实例化对象
  • 这里可以直接返回实例本身
  • 这个代码不用看,实际开发过程中用不到,我会做为一个甜点分享

其他地方的调用

├─finishBeanFactoryInitialization(beanFactory); Spring 核心方法中的
│ ├─beanFactory.preInstantiateSingletons();
│ │ ├─getBean(beanName);
│ │ │ ├─doGetBean(name, null, null, false);
│ │ │ │ ├─if (mbd.isSingleton()) {
│ │ │ │ │ ├─下面的 getSingleton 方法传入了一个 Lambda 表达式,并在 getSingleton 中调用了传入的 lambda 表达式,创建了 bean 实例。
│ │ │ │ │ ├─sharedInstance = getSingleton(beanName, () -> {
│ │ │ │ │ │ ├─return createBean(beanName, mbd, args);
│ │ │ │ │ │ │ ├─Object beanInstance = doCreateBean(beanName, mbdToUse, args);
│ │ │ │ │ │ │ │ ├─instanceWrapper = createBeanInstance(beanName, mbd, args);
│ │ │ │ │ │ │ │ ├─populateBean(beanName, mbd, instanceWrapper);
│ │ │ │ │ │ │ │ │ ├─if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {

这个地方的调用就很有意思了,populateBean 是用来做依赖注入的。而这里的代码如下:

java
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw){
    // 此处省略前面的代码
    if(!mbd.isSynthetic()&&hasInstantiationAwareBeanPostProcessors()){
        for(InstantiationAwareBeanPostProcessor bp:getBeanPostProcessorCache().instantiationAware){
            if(!bp.postProcessAfterInstantiation(bw.getWrappedInstance(),beanName)){
                return;
            }
        }
    }
    // 此处省略后面的代码
}

可以看出,假如我们写了一个类实现了 InstantiationAwareBeanPostProcessor,并在 postProcessAfterInstantiation 返回 false,如下:

java
@Component
public class DemoInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
    @Override
    public boolean postProcessAfterInstantiation(Object object, String beanName) {
        return false;
    }
}

那么程序执行到上面的 populateBean 方法时, 就直接 return 了,意味着后面的依赖注入都不会进行了。如果恶意人员使用这一点,就会造成项目工程异常。

SmartInstantiationAwareBeanPostProcessor

SmartInstantiationAwareBeanPostProcessor 继承了 InstantiationAwareBeanPostProcessor。

智能实例化 Bean 的后处理器,主要提供了三个方法:

  • predictBeanType:预测从此处理器的 postProcessBeforeInstantiation 回调最终返回的 bean 的类型。
  • determineCandidateConstructors:确定合适的实例化 Bean 的构造函数。
  • getEarlyBeanReference:获取提早暴露的 Bean 的引用,提早暴露的 Bean 就是只完成了实例化,还未完成属性赋值和初始化的 Bean。

这个接口是在哪儿调用的?

├─finishBeanFactoryInitialization(beanFactory); Spring 核心方法中的
│ ├─beanFactory.preInstantiateSingletons();
│ │ ├─getBean(beanName);
│ │ │ ├─doGetBean(name, null, null, false);
│ │ │ │ ├─if (mbd.isSingleton()) {
│ │ │ │ │ ├─下面的 getSingleton 方法传入了一个 Lambda 表达式,并在 getSingleton 中调用了传入的 lambda 表达式,创建了 bean 实例。
│ │ │ │ │ ├─sharedInstance = getSingleton(beanName, () -> {
│ │ │ │ │ │ ├─return createBean(beanName, mbd, args);
│ │ │ │ │ │ │ ├─Object beanInstance = doCreateBean(beanName, mbdToUse, args);
│ │ │ │ │ │ │ │ ├─instanceWrapper = createBeanInstance(beanName, mbd, args);
│ │ │ │ │ │ │ │ │ ├─Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
java
/**
 * 返回前正在实例化的bean中有@Autowired注解的构造函数
 */
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
			throws BeansException {

    if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
        // 拿到 BeanPostProcessor 的所有接口,遍历
        for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
            // 获取到有@Autowired注解信息的构造函数
            Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
            if (ctors != null) {
                return ctors;
            }
        }
    }
    return null;
}

AutowiredAnnotationBeanPostProcessor

AutowiredAnnotationBeanPostProcessor 继承了 SmartInstantiationAwareBeanPostProcessor。

TIP

SmartInstantiationAwareBeanPostProcessor 类中的 determineCandidateConstructors 方法,会调用其子类 AutowiredAnnotationBeanPostProcessor 中的 determineCandidateConstructors 方法,来获取到有@Autowired 注解信息的构造函数。

AutowiredAnnotationBeanPostProcessor 类会完成 @Autowired 和 @value 两个注解的扫描。

MergedBeanDefinitionPostProcessor

合并 Bean 的定义信息的后处理方法,该方法是在 Bean 的实例化之后设置值之前调用。