BeanPostProcessor原理分析

Posted Super_Leng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BeanPostProcessor原理分析相关的知识,希望对你有一定的参考价值。

文章目录

一、BeanPostProcessor的作用

  • BeanPostProcessor提供了初始化前后回调的方法,Spring中常见的扩展就是在初始化前后对Bean进行的扩展。
  • BeanDefinition注册完成之后,在创建Bean过程中的初始化前后分别调用其中定义的方法。

其操作对象为:已经实例化且进行了属性填充,待初始化的Bean实例。

1. 源码

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;
   

注意:方法的返回值为原始实例或者包装后的实例。如果返回null会导致后续的BeanPostProcessor不生效(BeanPostProcessor是可以注册多个的)。

2. 使用案例


public class BeanPostProcessorDemo 
    public static void main(String[] args) 
        // 创建基础容器
        // BeanFactory作为基础容器,可以手动将BeanPostProcessor注册到容器中去的。
		// 同时也可以采用扫描或者定义的方式注册到容器中。
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 加载xml配置文件
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
        reader.loadBeanDefinitions("spring-bean-post-processor.xml");
        // 添加BeanPostProcessor
        beanFactory.addBeanPostProcessor(new UserBeanPostProcessor());
        User user = beanFactory.getBean(User.class);
        System.out.println(user);
    

@Data
class User
    private String userName;
    private Integer age;
    private String beforeMessage;
    private String afterMessage;
    
    public void initMethod()
        System.out.println("初始化:"+this);
        this.setUserName("小明");
        this.setAge(18);
    

class UserBeanPostProcessor implements BeanPostProcessor
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) 
        throws BeansException 
        if (bean instanceof User)
            System.out.println("初始化前:"+bean);
            ((User) bean).setBeforeMessage("初始化前信息");
        
        return bean;
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
        if (bean instanceof User)
            System.out.println("初始化后:"+bean);
            ((User) bean).setAfterMessage("初始化后信息");
        
        return bean;
    

初始化前:User(userName=null, age=null, beforeMessage=null, afterMessage=null)
初始化:User(userName=null, age=null, beforeMessage=初始化前信息, afterMessage=null)
初始化后:User(userName=小明, age=18, beforeMessage=初始化前信息, afterMessage=null)
User(userName=小明, age=18, beforeMessage=初始化前信息, afterMessage=初始化后信息)

打印结果分析:

  1. 初始化前:User(userName=null, age=null, beforeMessage=null, afterMessage=null)
    该结果是postProcessBeforeInitialization方法中输出的内容,这个时候User实例还只是进行了实例化,还未进行到初始化步骤,所以所有的属性都为null,说明该方法确实是初始化执行的。——(此时的初始化指的是bean对象的init方法)
  2. 初始化:User(userName=null, age=null, beforeMessage=初始化前信息, afterMessage=null)
    该结果为自定义的初始化方法initMethod方法中输出的内容,这个时候User实例真正初始化,而beforeMessage中的值正是在postProcessBeforeInitialization设置的。
  3. 初始化后:User(userName=小明, age=18, beforeMessage=初始化前信息, afterMessage=null)
    该结果是postProcessAfterInitialization中输出内容,从打印结果可以看出它的确是在自定义initMethod后。

二、Spring生命周期中的BeanPostProcessor

Spring中Bean总体上来说可以分为四个周期:实例化、属性赋值、初始化、销毁。
而BeanPostProcessor则是在初始化阶段的前后执行。

首先看AbstractAutowireCapableBeanFactory源码中doCreateBean方法,该方法实际就是创建指定Bean的方法。
其中有三个重要的方法:createBeanInstance、populateBean、initializeBean。
这三个方法分别代表了Spring Bean中的实例化、属性赋值和初始化三个生命周期。

BeanPostProcessor是在初始化前后调用,所以查看initializeBean中的方法详情即可。

protected Object initializeBean(String beanName, Object bean, @Nullable 
                                RootBeanDefinition mbd) 
   // 处理BeanNameAware、BeanClassLoaderAware、BeanFactoryAware
   if (System.getSecurityManager() != null) 
         AccessController.doPrivileged((PrivilegedAction<Object>) () -> 
         invokeAwareMethods(beanName, bean);
         return null;
      , getAccessControlContext());
   
   else 
      invokeAwareMethods(beanName, bean);
   
   // 处理BeanPostProcessor
   Object wrappedBean = bean;
   if (mbd == null || !mbd.isSynthetic()) 
      // 回调postProcessBeforeInitialization方法
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
   
   try 
      // 处理InitializingBean和BeanDefinition中指定的initMethod
      invokeInitMethods(beanName, wrappedBean, mbd);
   
   catch (Throwable ex) 
           throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
   
   if (mbd == null || !mbd.isSynthetic()) 
      //回调postProcessAfterInitialization方法
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
   
   return wrappedBean;

从上面的源码可以看出首先是处理部分Aware相关接口,然后接着就是处理BeanPostProcessor中的postProcessBeforeInitialization方法,该方法详情如下:

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException 
   Object result = existingBean;
   // 依次处理BeanPostProcessor
   for (BeanPostProcessor processor : getBeanPostProcessors()) 
      Object current = processor.postProcessBeforeInitialization(result, beanName);
      // 如果放回null,则直接返回。后续BeanPostProcessor中的postProcessBeforeInitialization不再执行
      if (current == null) 
         return result;
      
      result = current;
   
   return result;

该方法就是执行postProcessBeforeInitialization回调的详情内容,从该实现可以知道,BeanPostProcessor可以有多个,而且会按照顺序依次处理。如果只要其中的任意一个返回null,则后续的BeanPostProcessor的postProcessBeforeInitialization将不会再处理了。

接着就是执行初始化方法,即invokeInitMethods方法被调用。

protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable 
   boolean isInitializingBean = (bean instanceof InitializingBean);
   if (isInitializingBean && (mbd == null ||    
        !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) 
      if (logger.isTraceEnabled()) 
         logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + 
            "'");
      
      // 如果当前Bean实现了InitializingBean接口则会执行它的afterPropertiesSet()方法
      if (System.getSecurityManager() != null) 
         try 
            AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> 
               ((InitializingBean) bean).afterPropertiesSet();
               return null;
            , getAccessControlContext());
         
         catch (PrivilegedActionException pae) 
            throw pae.getException();
         
      
      else 
         ((InitializingBean) bean).afterPropertiesSet();
      
   
   // 如果在BeanDefinition中定义了initMethod则执行初始化方法
   if (mbd != null && bean.getClass() != NullBean.class) 
      String initMethodName = mbd.getInitMethodName();
      if (StringUtils.hasLength(initMethodName) &&
            !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
            !mbd.isExternallyManagedInitMethod(initMethodName)) 
         invokeCustomInitMethod(beanName, bean, mbd);
      
   

从上面代码也进一步验证了BeanPostProcessor中的postProcessBeforeInitialization方法的确是在初始化前调用。
当invokeInitMethods执行之后接着就执行applyBeanPostProcessorsAfterInitialization方法。


@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException 
   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) 
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) 
         return result;
      
      result = current;
   
   return result;

该方法与applyBeanPostProcessorsBeforeInitialization几乎就是相同的,不同的在于它执行的是postProcessAfterInitialization。至此Spring Bean的初始化也就完成了。

三、BeanPostProcessor对@PostConstruct的支持

通过上面了解了Spring Bean生命周期中初始化的过程,但实际上Spring对于JSR250也支持,例如对@PostConstruct注解的支持。
在Spring中有一个CommonAnnotationBeanPostProcessor类,这个类的注释中有说到这个类就是用来对JSR250及其他一些规范的支持。

从上图中我们可以看出,CommonAnnotationBeanPostProcessor并没有直接对BeanPostProcessor有所实现,它继承InitDestroyAnnotationBeanPostProcessor该类,而对@PostConstruct的实现主要在该类中。

而对BeanPostProcessor的实现代码如下:

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 
   // 1.生命周期元数据封装
   LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
   try 
      // 2.执行InitMethods
      metadata.invokeInitMethods(bean, beanName);
   
   catch (InvocationTargetException ex) 
      throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
   
   catch (Throwable ex) 
      throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
   
   return bean;

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
   return bean;

对BeanPostProcessor的实现主要在before方法中,该方法主要就是两部分内容,第一部分主要是将信息封装到LifecycleMetadata中,便于后面第二步的执行相关初始化方法。

案例:


public class BeanPostProcessorDemo2 
    public static void main(String[] args) 
        // 创建基础容器
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 构建BeanDefinition并注册
        AbstractBeanDefinition beanDefinition = 
            BeanDefinitionBuilder.genericBeanDefinition(Person.class)
                .getBeanDefinition();
        beanFactory.registerBeanDefinition("person",beanDefinition);
        // 注册CommonAnnotationBeanPostProcessor
        CommonAnnotationBeanPostProcessor commonAnnotationBeanPostProcessor 
            = new CommonAnnotationBeanPostProcessor();
        beanFactory.addBeanPostProcessor(commonAnnotationBeanPostProcessor);
        // 获取Bean
        Person person = beanFactory.getBean(Person.class);
        System.out.println(person);
    


class Person
    @PostConstruct
    public void annotationInitMethod()
        System.out.println("@PostConstruct");
    


上面的代码定义了一个Person类并使用@PostConstruct标记出它的初始化方法,然后创建BeanFactory,并创建Person的BeanDefinition将其注册到BeanFactory(与读取配置文件一样),然后创建CommonAnnotationBeanPostProcessor并将其添加到BeanFactory中。

最后打印结果会打印出@PostConstruct。如果我们将下面这句代码注释。
beanFactory.addBeanPostProcessor(commonAnnotationBeanPostProcessor);
再次执行可以发现,@PostConstruct将会失效,且最后不会打印出结果。

四、BeanPostProcessor中的顺序性

BeanPostProcessor是可以注册多个的,在AbstractBeanFactory内部通过List变量beanPostProcessors来存储BeanPostProcessor。而在执行时是按照List中BeanPostProcessor的顺序一个个执行的,所以我们在想容器中添加BeanPostProcessor时需要注意顺序。如果我们不是通过手动添加(大多数时候不是)时,而是在代码或者配置文件中定义多个BeanPostProcessor时,我们可以通过实现Ordered接口来控制它的顺序。

BeanPostProcessor依赖的Bean是不会执行BeanPostProcessor的,这是因为在创建BeanPostProcessor时,其所依赖的Bean就需要完成初始化,而这个时候BeanPostProcessor都还未完初始化完成。

此外我们需要了解:@PostConstruct 执行点(beforeInitialization) 要早于 afterProperitesSet(invokeInitMethod-1) 早于对应的Bean定义的initMethod(invokeinitiMethod-2)方法的执行。

案例:

public class App3 
    public static void main(String[] args) 
        AnnotationConfigApplicationContext context = new 
        AnnotationConfigApplicationContext();
        context.scan("com.buydeem.beanpostprocessor");
        context.register(App3.class);
        context.refresh();
    


@Component
class ClassA


@Component
class ClassB


@Component
class MyBeanPostProcessor implements BeanPostProcessor
    @Autowired
    private ClassA classA;
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) 
        throws BeansException 
        System.out.println("MyBeanPostProcessor"+bean);
        return bean;
    

注意:最后ClassA是不会打印出来的,而ClassB是会被打印出来。因为MyBeanPostProcessor依赖了ClassA实例,ClassA会先初始化完成。

五、总结

Spring中BeanPostProcessor的子接口或实现类有很多种,例如:InstantiationAwareBeanPostProcessor、MergedBeanDefinitionPostProcessor、DestructionAwareBeanPostProcessor等。
这些接口分别处在Spring Bean生命周期的不同阶段,而他们的功能与BeanPostProcessor都类似,都是为了给Spring Bean各个生命周期提供扩展点。

Spring IOC 容器源码分析 - getBean调用方法解析 -- Bean的初始化之BeanPostProcessor

1.BeanPostProcessor接口


 

Spring 作为优秀的开源框架,它为我们提供了丰富的可扩展点,除了前面提到的 Aware 接口,还包括其他部分,其中一个很重要的就是 BeanPostProcessor。这篇文章主要介绍 BeanPostProcessor 的使用以及其实现原理。我们先看 BeanPostProcessor 的定位:

BeanPostProcessor 的作用:在 Bean 完成实例化后,如果我们需要对其进行一些配置、增加一些自己的处理逻辑,那么请使用 BeanPostProcessor。

2.BeanPostProcessor实例

首先定义一个类,该类实现BeanPostProcessor接口,代码如下:

public class BeanPostProcessorTest implements BeanPostProcessor{

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Bean [" + beanName + "] 开始初始化");
        // 这里一定要返回 bean,不能返回 null
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Bean [" + beanName + "] 完成初始化");
        return bean;
    }

    public void display(){
        System.out.println("hello BeanPostProcessor!!!");
    }
}

测试方法如下:

ClassPathResource resource = new ClassPathResource("spring.xml");
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(resource);

BeanPostProcessorTest test = (BeanPostProcessorTest) factory.getBean("beanPostProcessorTest");
test.display();

运行结果:

 

 

   运行结果比较奇怪,为什么没有执行 #postProcessBeforeInitialization(...) 和 #postProcessAfterInitialization(...) 方法呢?

   我们 debug 跟踪下代码,这两个方法在 AbstractAutowireCapableBeanFactory 的 #initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) 方法处调用下,如下:

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            // 若 bean 实现了 BeanNameAware、BeanFactoryAware、BeanClassLoaderAware 等接口,则向 bean 中注入相关对象
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // 执行 bean 初始化前置操作
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            /*
             * 调用初始化方法:
             * 1. 若 bean 实现了 InitializingBean 接口,则调用 afterPropertiesSet 方法
             * 2. 若用户配置了 bean 的 init-method 属性,则调用用户在配置中指定的方法
             */
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            // 执行 bean 初始化后置操作,AOP 会在此处向目标对象中织入切面逻辑
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

一起来看看applyBeanPostProcessorsBeforeInitialization

    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor processor : getBeanPostProcessors()) {//通过getBeanPostProcessors()获取所有
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }

  这段代码是通过迭代 #getBeanPostProcessors() 方法返回的结果集来调用 BeanPostProcessor 的 #postProcessBeforeInitialization(Object bean, String beanName) 方法,在我们的代码执行过过程中getBeanPostProcessors()返回为空

,所以肯定不会执行相应的 #postProcessBeforeInitialization(Object bean, String beanName) 方法咯。怎么办?答案不言而喻:只需要 #getBeanPostProcessors() 方法,返回的结果集中存在至少一个元素即可,该方法定义如下:

 

// AbstractBeanFactory.java

/** BeanPostProcessors to apply in createBean. */
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();

public List<BeanPostProcessor> getBeanPostProcessors() {
    return this.beanPostProcessors;
}

 

  返回的 beanPostProcessors 是一个 private 的 List ,也就是说只要该类中存在 beanPostProcessors.add(BeanPostProcessor beanPostProcessor) 的调用,我们就找到了入口,在类 AbstractBeanFactory 中找到了如下代码:

    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
        // Remove from old position, if any
        this.beanPostProcessors.remove(beanPostProcessor);
        // Track whether it is instantiation/destruction aware
        if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
            this.hasInstantiationAwareBeanPostProcessors = true;
        }
        if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
            this.hasDestructionAwareBeanPostProcessors = true;
        }
        // Add to end of list
        this.beanPostProcessors.add(beanPostProcessor);
    }

  该方法是由 AbstractBeanFactory 的父类 org.springframework.beans.factory.config.ConfigurableBeanFactory 接口定义,它的核心意思就是将指定 BeanPostProcessor 注册到该 BeanFactory 创建的 bean 中,同时它是按照插入的顺序进行注册的,完全忽略 Ordered 接口所表达任何排序语义(在 BeanPostProcessor 中我们提供一个 Ordered 顺序,这个后面讲解)。

  • 我们的代码之所以没有执行相应的代码是因为:getBean放中没有注入BeanPostProcess,所以想要BeanFactory容器的BeanPostProcessor生效我们必须手动调用#addBeanPostProcessor(BeanPostProcessor beanPostProcessor) 方法,将定义的 BeanPostProcessor 注册到相应的 BeanFactory 中

3.BeanPostProcessor基本原理


 

org.springframework.beans.factory.config.BeanPostProcessor 接口,代码如下:

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;
    }

}

  BeanPostProcessor 可以理解为是 Spring 的一个工厂钩子(其实 Spring 提供一系列的钩子,如 Aware 、InitializingBean、DisposableBean),它是 Spring 提供的对象实例化阶段强有力的扩展点,允许 Spring 在实例化 bean 阶段对其进行定制化修改,比较常见的使用场景是处理标记接口实现类或者为当前对象提供代理实现(例如 AOP)。

  一般普通的 BeanFactory 是不支持自动注册 BeanPostProcessor 的,需要我们手动调用 #addBeanPostProcessor(BeanPostProcessor beanPostProcessor) 方法进行注册。注册后的 BeanPostProcessor 适用于所有该 BeanFactory 创建的 bean,但是 ApplicationContext 可以在其 bean 定义中自动检测所有的 BeanPostProcessor 并自动完成注册,同时将他们应用到随后创建的任何 Bean 中

#postProcessBeforeInitialization(Object bean, String beanName) 和 #postProcessAfterInitialization(Object bean, String beanName) 两个方法,都接收一个 Object 类型的 bean ,一个 String 类型的 beanName ,其中 bean 是已经实例化了的 instanceBean ,能拿到这个你是不是可以对它为所欲为了? 这两个方法是初始化 bean 的前后置处理器,他们应用 #invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) 方法的前后。如下图:

 

 代码层次上面已经贴出来,这里再贴一次:

    protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                invokeAwareMethods(beanName, bean);
                return null;
            }, getAccessControlContext());
        }
        else {
            // 若 bean 实现了 BeanNameAware、BeanFactoryAware、BeanClassLoaderAware 等接口,则向 bean 中注入相关对象
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            // 执行 bean 初始化前置操作
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            /*
             * 调用初始化方法:
             * 1. 若 bean 实现了 InitializingBean 接口,则调用 afterPropertiesSet 方法
             * 2. 若用户配置了 bean 的 init-method 属性,则调用用户在配置中指定的方法
             */
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }
        if (mbd == null || !mbd.isSynthetic()) {
            // 执行 bean 初始化后置操作,AOP 会在此处向目标对象中织入切面逻辑
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
    }

两者源码如下:

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {
    Object result = existingBean;
    // 遍历 BeanPostProcessor 数组
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        // 处理
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        // 返回空,则返回 result
        if (current == null) {
            return result;
        }
        // 修改 result
        result = current;
    }
    return result;
}

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {
    Object result = existingBean;
    // 遍历 BeanPostProcessor
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        // 处理
        Object current = processor.postProcessAfterInitialization(result, beanName);
        // 返回空,则返回 result
        if (current == null) {
            return result;
        }
        // 修改 result
        result = current;
    }
    return result;
}

3.1 自动检测并注册

#getBeanPostProcessors() 方法,返回的是 beanPostProcessors 集合,该集合里面存放就是我们自定义的 BeanPostProcessor ,如果该集合中存在元素则调用相应的方法,否则就直接返回 bean 了。这也是为什么使用 BeanFactory 容器是无法输出自定义 BeanPostProcessor 里面的内容,因为在 BeanFactory#getBean(...) 方法的过程中根本就没有将我们自定义的 BeanPostProcessor 注入进来,所以要想 BeanFactory 容器 的 BeanPostProcessor 生效我们必须手动调用 #addBeanPostProcessor(BeanPostProcessor beanPostProcessor) 方法,将定义的 BeanPostProcessor 注册到相应的 BeanFactory 中。但是 ApplicationContext 不需要手动,因为 ApplicationContext 会自动检测并完成注册

ApplicationContext 实现自动注册的原因,在于我们构造一个 ApplicationContext 实例对象的时候会调用 #registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) 方法,将检测到的 BeanPostProcessor 注入到 ApplicationContext 容器中,同时应用到该容器创建的 bean 中。代码如下:

    public static void registerBeanPostProcessors(
            ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
        // 获取所有的 BeanPostProcessor 的 beanName
        // 这些 beanName 都已经全部加载到容器中去,但是没有实例化
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

        // 记录所有的beanProcessor数量
        int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
        // 注册 BeanPostProcessorChecker,它主要是用于在 BeanPostProcessor 实例化期间记录日志
        // 当 Spring 中配置的后置处理器还没有注册就已经开始了 bean 的实例化过程,这个时候便会打印 BeanPostProcessorChecker 中的内容
        beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

        // PriorityOrdered 保证顺序
        List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
        // 使用 Ordered 保证顺序
        List<String> orderedPostProcessorNames = new ArrayList<>();
        // 没有顺序
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                // 调用 getBean 获取 bean 实例对象
                BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
                priorityOrderedPostProcessors.add(pp);
                if (pp instanceof MergedBeanDefinitionPostProcessor) {
                    internalPostProcessors.add(pp);
                }
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                // 有序 Ordered
                orderedPostProcessorNames.add(ppName);
            }
            else {
                // 无序
                nonOrderedPostProcessorNames.add(ppName);
            }
        }

        // 第一步,注册所有实现了 PriorityOrdered 的 BeanPostProcessor
        // 先排序
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        // 后注册
        registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

        // 第二步,注册所有实现了 Ordered 的 BeanPostProcessor
        List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
        for (String ppName : orderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            orderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        // 先排序
        sortPostProcessors(orderedPostProcessors, beanFactory);
        // 后注册
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);

        // 第三步注册所有无序的 BeanPostProcessor
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
        for (String ppName : nonOrderedPostProcessorNames) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            nonOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        // 注册,无需排序
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

        // 最后,注册所有的 MergedBeanDefinitionPostProcessor 类型的 BeanPostProcessor
        sortPostProcessors(internalPostProcessors, beanFactory);
        registerBeanPostProcessors(beanFactory, internalPostProcessors);

        // 加入ApplicationListenerDetector(探测器)
        // 重新注册 BeanPostProcessor 以检测内部 bean,因为 ApplicationListeners 将其移动到处理器链的末尾
        beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
    }
  • 方法首先 beanFactory 获取注册到该 BeanFactory 中所有 BeanPostProcessor 类型的 beanName 数组,其实就是找所有实现了 BeanPostProcessor 接口的 bean ,然后迭代这些 bean ,将其按照 PriorityOrdered、Ordered、无序的顺序,添加至相应的 List 集合中,最后依次调用 #sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) 方法来进行排序处理、 #registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) 方法来完成注册。
  • 排序】很简单,如果 beanFactory 为 DefaultListableBeanFactory ,则返回 BeanFactory 所依赖的比较器,否则反正默认的比较器(OrderComparator),然后调用 List#sort(Comparator<? super E> c) 方法即可。代码如下:

 

// PostProcessorRegistrationDelegate.java
private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    // 获得 Comparator 对象
    Comparator<Object> comparatorToUse = null;
    if (beanFactory instanceof DefaultListableBeanFactory) { // 依赖的 Comparator 对象
        comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
    }
    if (comparatorToUse == null) { // 默认 Comparator 对象
        comparatorToUse = OrderComparator.INSTANCE;
    }
    // 排序
    postProcessors.sort(comparatorToUse);
}
  • 而对于【注册】,同样是调用 AbstractBeanFactory#addBeanPostProcessor(BeanPostProcessor beanPostProcessor) 方法完成注册。代码如下:
// PostProcessorRegistrationDelegate.java

private static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
    // 遍历 BeanPostProcessor 数组,注册
    for (BeanPostProcessor postProcessor : postProcessors) {
        beanFactory.addBeanPostProcessor(postProcessor);
    }
}

 

4.结语


 

至此,BeanPostProcessor 已经分析完毕了,这里简单总结下:

  • BeanPostProcessor 的作用域是容器级别的,它只和所在的容器相关 ,当 BeanPostProcessor 完成注册后,它会应用于所有跟它在同一个容器内的 bean 。
  • BeanFactory 和 ApplicationContext 对 BeanPostProcessor 的处理不同,ApplicationContext 会自动检测所有实现了 BeanPostProcessor 接口的 bean,并完成注册,但是使用 BeanFactory 容器时则需要手动调用 AbstractBeanFactory#addBeanPostProcessor(BeanPostProcessor beanPostProcessor) 方法来完成注册
  • ApplicationContext 的 BeanPostProcessor 支持 Ordered,而 BeanFactory 的 BeanPostProcessor 是不支持的,原因在于ApplicationContext 会对 BeanPostProcessor 进行 Ordered 检测并完成排序,而 BeanFactory 中的 BeanPostProcessor 只跟注册的顺序有关。

 

以上是关于BeanPostProcessor原理分析的主要内容,如果未能解决你的问题,请参考以下文章

BeanPostProcessor后置处理器原理以及ApplicationListener原理

springboot:BeanPostProcessor示例及分析

Spring生命周期-BeanFactoryPostProcessor和BeanPostProcessor

spring-aop代理的生效原理

Spring原理篇--BeanPostProcessor or BeanDefinition or Aware or InitializingBean

简单分析BeanPostProcessor