Spring的后处理器-BeanPostProcessor跟BeanFactoryPostProcessors

Spring的后处理器只要有两大类,一个是针对BeanDefinition的容器级别的后处理器 - BeanFactoryPostProcessor(后面简称BFPP);一个是针对getBean操作获得的对象的后处理器 -BeanPostProcessor(后面简称BPP)。

此两个后处理器不同之处主要有三点:

  • 1、触发时机不同,前者BFPP是在容器refresh方法中调用,而后者实际调用时机是在getBean方法获取对象时调用;
  • 2、因触发时机不同导致二者处理的对象不同。BFPP处理的是解析完配置文件后注册在容器中的BeanDefinition,而BPP处理的是通过反射生成的实例Bean;
  • 3、接口样式不同,BFPP只有一个后处理方法,而BPP有一个前置处理方法一个后置处理方法。
public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}


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

    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

}

一:BeanFactoryPostProcessor                                                                                            

在ApplicationContext容器初始化的核心方法refresh方法中,初始化完BeanFactory后会执行invokeBeanFactoryPost Processors方法,就是在此方法中完成了对BFPP的调用。代码如下所示:

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
}

可以知道,完成后处理器调用的方法是第二行的代码。此处请记住这个类PostProcessorRegistrationDelegate,它是处理后处理器的核心类。对于此处的方法invokeBeanFactoryPostProcessors,

代码很长,就不贴出来了,下面只做一些简单的梳理。

  1. 先判断当前BeanFactory是不是BeanDefinitionRegistry,如果是则将实现BeanDefinitionRegistryPostProcessor(简称BDRPP)接口的类找到,按顺序执行后处理器的方法。此BDRPP接口是BFPP接口的子类。其作用是什么?为什么要单独对其进行处理?看其后置方法便可只其一二。它的后置处理方法参数是一个BeanDefinitionRegistry,它是做什么用的?往容器中注册BeanDefinition的。所以此处单独处理BDRPP的原因也就基本明了了 - 就是根据实际需要在此处创建BeanDefinition往容器中注册的,即留了一个往容器中注册bean的后门。
  2. 再获取所有实现了BeanFactoryPostProcessor接口的子类,按照顺序执行后处理器方法。

二:BeanPostProcessor                                                                                                         

        BPP后处理器的处理,相比BFPP多了一步,BFPP是在ApplicationContext容器初始化的时候就调用了,而BPP是在容器初始化时注册,调用则是在getBean获取对象实例时触发。

1、BPP的注册

        同样是在refresh方法中,就在调用BFPP方法的下面,调用了注册BPP的方法  - registerBeanPostProcessors方法。

 protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
 }

看到熟悉的面孔了吧,对,还是它,那个调用BFPP的类!

此方法代码同样不少,此处就不贴出来了,主要梳理一下代码逻辑:

  1. 首先是获取BPP实例。获取BPP子类的套路跟上文中获取BFPP子类的套路基本一样,先通过类的type获取到注册到当前容器中的所有的子类,然后根据是否实现了PriorityOrdered、Ordered接口对其进行分类、排序,最后再通过beanFactory的getBean方法获取到BeanPostProcessor的实例对象;
  2. 注册BPP实例。注册的顺序是先注册实现了PriorityOrdered的实例,再注册Ordered的实例,最后注册普通的BPP。此处的注册是指将这个BPP放入AbstractBeanFactory维护的一个成员变量中,此变量是一个CopyOnWriteArrayList。在加入之前会先执行一下remove方法,防止重复加入。

2、BPP的调用

         BeanFactory的多个getBean方法,大多是在AbstractBeanFactory方法中实现,而最终创建bean实例,则是在AbstractAutowireCapableBeanFactory中实现。在此类的doCreateBean方法的initializeBean方法中,实现了对BPP的调用。方法代码如下所示:

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 {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }//此处catch异常处理代码已被BZ去掉
        
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

        return wrappedBean;
}

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值