spring源码-bean的后置处理器

spring源码-bean的后置处理器_第1张图片

 

BeanPostProcessor

BeanPostProcessor也称为Bean后置处理器,它是Spring中定义的接口,在Spring容器的创建过程中(具体为Bean初始化前后)会回调BeanPostProcessor中定义的两个方法。

BeanPostProcessor的源码如下:

public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

其中

方法

描述

postProcessBeforeInitialization

方法会在每一个bean对象的初始化方法调用之前回调;

postProcessAfterInitialization

方法会在每个bean对象的初始化方法调用之后被回调。具体执行时期可以参考Spring中Bean的生命周期源码探究。

查看BeanPostProcessor源码,可以看到它两个方法的参数都相同,其中第一个参数Object bean表示当前正在初始化的bean对象。此外两个方法都返回Object类型的实例,返回值既可以是将入参Object bean原封不动的返回出去,也可以对当前bean进行包装再返回。

spring源码-bean的后置处理器_第2张图片

InstantiationAwareBeanPostProcessor

InstantiationAwareBeanPostProcessor继承自BeanPostProcessor 是spring非常重要的拓展接口,代表这bean的一段生命周期: 实例化(Instantiation)

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

    @Nullable
    default Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
        return null;
    }

    default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        return true;
    }

    @Nullable
    default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
            throws BeansException {

        return null;
    }

    @Deprecated
    @Nullable
    default PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {

        return pvs;
    }

}

方法

描述

postProcessBeforeInstantiation

最先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走

postProcessAfterInstantiation

在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessProperties方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessProperties就会被忽略不执行;如果返回true,postProcessProperties就会被执行

postProcessProperties

对属性值进行修改,如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用。可以在该方法内对属性值进行修改

测试:

@Component
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
   /**
    * BeanPostProcessor接口中的方法
    * 在Bean的自定义初始化方法之前执行
    * Bean对象已经存在了
    */
   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      // TODO Auto-generated method stub
      System.out.println(">>postProcessBeforeInitialization");
      return bean;
   }

   /**
    * BeanPostProcessor接口中的方法
    * 在Bean的自定义初始化方法执行完成之后执行
    * Bean对象已经存在了
    */
   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
      System.out.println("< beanClass, String beanName) throws BeansException {
      System.out.println("--->postProcessBeforeInstantiation");
      return null;
   }

   /**
    * InstantiationAwareBeanPostProcessor中自定义的方法
    * 在方法实例化之后执行  Bean对象已经创建出来了
    */
   @Override
   public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
      System.out.println("<---postProcessAfterInstantiation");
      return true;
   }

   /**
    * InstantiationAwareBeanPostProcessor中自定义的方法
    * 可以用来修改Bean中属性的内容
    * 取代过时的postProcessPropertyValues方法
    */
   @Override
   public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
      System.out.println("<---postProcessProperties--->");
      return pvs;
   }
}

输出:

Task :spring-demo:RunApp.main()
--->postProcessBeforeInstantiation
<---postProcessAfterInstantiation
<---postProcessProperties--->
postProcessBeforeInitialization
<

spring源码-bean的后置处理器_第3张图片

SmartInstantiationAwareBeanPostProcessor

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
   @Nullable
   default Class predictBeanType(Class beanClass, String beanName) throws BeansException {
      return null;
   }
   @Nullable
   default Constructor[] determineCandidateConstructors(Class beanClass, String beanName)
         throws BeansException {
      return null;
   }
   default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
      return bean;
   }
}

方法

描述

predictBeanType

predictBeanType:该触发点发生在postProcessBeforeInstantiation之前,这个方法用于预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null;当你调用BeanFactory.getType(name)时当通过bean的名字无法得到bean类型信息时就调用该回调方法来决定类型信息

determineCandidateConstructors

该触发点发生在postProcessBeforeInstantiation之后,用于确定该bean的构造函数之用,返回的是该bean的所有构造函数列表。用户可以扩展这个点,来自定义选择相应的构造器来实例化这个bean。

getEarlyBeanReference

getEarlyBeanReference:该触发点发生在postProcessAfterInstantiation之后,当有循环依赖的场景,当bean实例化好之后,为了防止有循环依赖,会提前暴露回调方法,用于bean实例化的后置处理。这个方法就是在提前暴露的回调方法中触发。

测试:

package com.sqz.ioc.beanpostprocess;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.beans.BeansException;
import org.springframework.stereotype.Component;

import java.lang.reflect.Constructor;
@Component
public class MySmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {


   /**
    * 预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null
    * @param beanClass
    * @param beanName
    * @return
    * @throws BeansException
    */
   @Override
   public Class predictBeanType(Class beanClass, String beanName) throws BeansException {
      System.out.println("MySmartInstantiationAwareBeanPostProcessor.predictBeanType,beanName:"+beanName);
      return null;
   }

   /**
    * 选择合适的构造器,比如目标对象有多个构造器,在这里可以进行一些定制化,选择合适的构造器
    *
    * @param beanClass : beanClass参数表示目标实例的类型
    * @param beanName : beanName是目标实例在Spring容器中的name
    * @return  : 返回值是个构造器数组,如果返回null,会执行下一个PostProcessor的determineCandidateConstructors方法;否则选取该PostProcessor选择的构造器
    * @throws BeansException
    */
   @Override
   public Constructor[] determineCandidateConstructors(Class beanClass, String beanName) throws BeansException {
      System.out.println("MySmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors,beanName:"+beanName);
      return null;
   }


   /**
    *  获得提前暴露的bean引用,主要用于解决循环引用的问题
    *  (只有单例对象才会调用此方法)
    * @param bean
    * @param beanName
    * @return
    * @throws BeansException
    */
   @Override
   public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
      System.out.println("MySmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference,beanName:"+beanName);
      return null;
   }

}

MergedBeanDefinitionPostProcessor

public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {

   /**
    * Post-process the given merged bean definition for the specified bean.
    * @param beanDefinition the merged bean definition for the bean
    * @param beanType the actual type of the managed bean instance
    * @param beanName the name of the bean
    * @see AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
    */
   void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class beanType, String beanName);

   /**
    * A notification that the bean definition for the specified name has been reset,
    * and that this post-processor should clear any metadata for the affected bean.
    * 

The default implementation is empty. * @param beanName the name of the bean * @since 5.1 * @see DefaultListableBeanFactory#resetBeanDefinition */ default void resetBeanDefinition(String beanName) { } }

方法

描述

postProcessMergedBeanDefinition

创建完 bean 实例之后,填充属性之前调用

一般做注解扫描

resetBeanDefinition

DefaultListableBeanFactory # registerBeanDefinition调用

一般做移除缓存

 DefaultListableBeanFactory # registerBeanDefinition


public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      throws BeanDefinitionStoreException {
   // S1 : 会对 BeanDefinition 进行校验 , 主要是MethodOverrides和FactoryMethodName不能同时存在
   // -- 工厂方法必须创建具体的 Bean 实例 , 而 methodOverrides 会创建代理类且进行增强
   // -- 也就是说 工厂需要实例 , 不能是代理类
   if (beanDefinition instanceof AbstractBeanDefinition) {
       ((AbstractBeanDefinition) beanDefinition).validate();
   }
   // S2 : 判断 BeanDefinition 是否已经存在
   BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
   if (existingDefinition != null) {
      // 是否允许同名Bean重写 , 因为此处已经存在一个了 , 不能重写则直接异常 
      if (!isAllowBeanDefinitionOverriding()) {
         throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
      }else if (existingDefinition.getRole() < beanDefinition.getRole()) {
          // 角色比较 ,只打日志 
          // ROLE_APPLICATION / ROLE_SUPPORT / ROLE_INFRASTRUCTURE
      }else if (!beanDefinition.equals(existingDefinition)) {
          // 判断是否为同一对象
      }
      // 以上主要是打log , 这里如果允许覆盖则直接覆盖了
      this.beanDefinitionMap.put(beanName, beanDefinition);
   }
   else {
      // 判断该Bean是否已经开始初始化
      if (hasBeanCreationStarted()) {
         // 如果已经开始 , 需要对 Map 上锁后再处理
         synchronized (this.beanDefinitionMap) {
            this.beanDefinitionMap.put(beanName, beanDefinition);
            // 省略一些更新操作
         }
      }
      else {
         // 没有加载时的载入
         this.beanDefinitionMap.put(beanName, beanDefinition);
         this.beanDefinitionNames.add(beanName);
         removeManualSingletonName(beanName);
      }
      this.frozenBeanDefinitionNames = null;
   }
   // 如果Bean已经存在或已经开始加载了 , 这个时候时需要进行销毁操作的
   if (existingDefinition != null || containsSingleton(beanName)) {
      resetBeanDefinition(beanName);
   }
}
protected void resetBeanDefinition(String beanName) {
   // S1 : 如果已经创建 ,需要清空 Merge BeanDefinition
   clearMergedBeanDefinition(beanName);
   // S2 : 销毁 Bean
   destroySingleton(beanName);
   // S3 : 调用 PostProcessors 重置处理器进行处理
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      if (processor instanceof MergedBeanDefinitionPostProcessor) {
         ((MergedBeanDefinitionPostProcessor) processor).resetBeanDefinition(beanName);
      }
   }
   // S4 : 如果该 BeanDefinition 是某个BeanDefinition 的Parent , 则需要同步处理
   for (String bdName : this.beanDefinitionNames) {
      if (!beanName.equals(bdName)) {
         BeanDefinition bd = this.beanDefinitionMap.get(bdName);
         if (bd != null && beanName.equals(bd.getParentName())) {
            resetBeanDefinition(bdName);
         }
      }
   }
}

你可能感兴趣的:(spring源码,spring,java,后端)