[Spring]Spring的PostProcessor-后置處理器

PostProcessor

為什么要有這個(gè)后置處理器這種接口,了解Spring容器的朋友應(yīng)該知道,所有的ApplicationContext都需要調(diào)用AbstractApplicationContext#refresh方法,這是一個(gè)模板方法,既然使用了模板方法設(shè)計(jì)模式,那么就應(yīng)該提供hook,也就是鉤子函數(shù)。而PostProcessor就是為了實(shí)現(xiàn)這種定制化的擴(kuò)展需求而制定的。

UML

  • BeanPostProcessor

    BeanPostProcessor

  • BeanFactoryPostProcessor

    BeanFactoryPostProcessor

PostProcessor概覽

BeanFactoryPostProcessor

容器級(jí)別的后置處理器,其內(nèi)部僅聲明了一個(gè)方法。Spring會(huì)根據(jù)聲明的順序?qū)笾锰幚砥鬟M(jìn)行調(diào)用,而BeanFactoryPostProcessor會(huì)在容器初始化期間將容器本身交由接口實(shí)現(xiàn)類去處理。獲取到了容器,就可以做很多定制化的操作了。

@FunctionalInterface
public interface BeanFactoryPostProcessor {

    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for overriding or adding
     * properties even to eager-initializing beans.
     * @param beanFactory the bean factory used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}
BeanDefinitionRegistryPostProcessor

從注解容器解析BeanDefinition的篇章中,你會(huì)了解到BeanDefinitionRegistryPostProcessor是一種特殊的BeanFactoryPostProcessor,但是Spring會(huì)優(yōu)先處理這類后置處理器,再處理常規(guī)的一些BeanFactoryPostProcessor.可以理解成VIP級(jí)別的BeanFactoryPostProcessor,優(yōu)先于常規(guī)BeanFactoryPostProcessor執(zhí)行。
其內(nèi)部也聲明了一個(gè)專用的注冊(cè)后置處理方法。postProcessBeanDefinitionRegistry

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

    /**
     * Modify the application context's internal bean definition registry after its
     * standard initialization. All regular bean definitions will have been loaded,
     * but no beans will have been instantiated yet. This allows for adding further
     * bean definitions before the next post-processing phase kicks in.
     * @param registry the bean definition registry used by the application context
     * @throws org.springframework.beans.BeansException in case of errors
     */
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

BeanPostProcessor

容器創(chuàng)建Bean時(shí)的hook實(shí)例,你可以通過實(shí)現(xiàn)BeanPostProcessor來影響所有Bean的生命周期,包括Initialization的前置與后置處理.在后面學(xué)習(xí)Spring Bean的生命周期中,會(huì)接觸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;
    }

}

使用postProcessor

MyBeanFactoryPostProcessor

  • 基礎(chǔ)對(duì)象
@Data
public class Root {

    private String name;

    private String description;

    private boolean isRoot;
}
  • 通過后置處理器往容器注入BeanDefinition
package com.xjm.bean.postprocessor;

import com.xjm.model.Root;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.context.annotation.Configuration;

/**
 * @author jaymin
 * 2021/1/7 23:10
 */
@Configuration
public class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

    }

    /**
     * 標(biāo)準(zhǔn)初始化后,修改應(yīng)用程序上下文的內(nèi)部BeanDefiniton注冊(cè)表。<br>
     * 所有常規(guī)bean定義都將被加載,但尚未實(shí)例化任何bean。 <br>
     * 這允許在下一個(gè)后處理階段開始之前添加更多的BeanDeinition。 <br>
     * Spring工廠級(jí)別的BeanFactoryPostProcessor,優(yōu)先級(jí)別高于常規(guī)的BeanFactoryPostProcessor.<br>
     * 第三方框架整合時(shí),可以實(shí)現(xiàn)這個(gè)注冊(cè)接口進(jìn)行BeanDefinition注冊(cè).如Mybatis.<br>
     * 設(shè)計(jì)模式:責(zé)任鏈模式<br>
     * @param registry the bean definition registry used by the application context
     * @throws BeansException
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        BeanDefinition beanDefinition = getBeanDefinition(Root.class);
        registry.registerBeanDefinition("root",beanDefinition);
        System.out.println("Customer BeanPostProcessors execute.");
    }

    private BeanDefinition getBeanDefinition(Class<?> clazz){
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(clazz).getBeanDefinition();
        return beanDefinition;
    }
}
  • test

@ComponentScan根據(jù)自己的包路徑進(jìn)行修改,此處程序正常運(yùn)行,說明Root已經(jīng)注冊(cè)到容器中了.

@Configuration
@ComponentScan(value = "com.xjm")
public class BeanDefinitionDemoByAnnotation {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationContextDemo.class);
        Root root = applicationContext.getBean("root", Root.class);
    }
}

MyBeanPostProcessor

簡(jiǎn)單實(shí)現(xiàn)BeanPostProcessor,主要是觀察其行為的作用域.

@Configuration
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    @Nullable
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + " invoking MyBeanPostProcessor#postProcessBeforeInitialization");
        return bean;
    }

    /**
     * 可以對(duì)所有的Bean做統(tǒng)一操作
     * @param bean the new bean instance
     * @param beanName the name of the bean
     * @return
     * @throws BeansException
     */
    @Override
    @Nullable
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + " invoking MyBeanPostProcessor#postProcessAfterInitialization");
        return bean;
    }

}
  • result
result

可以看到,實(shí)現(xiàn)的MyBeanPostProcessor影響了所有Bean的初始化過程.

總結(jié)

  • 后置處理器是Spring留給開發(fā)者的擴(kuò)展性鉤子接口。
  • 從后置處理器上可以簡(jiǎn)略分為:BeanFactoryPostProcessorBeanPostProcessor.其中,BeanFactoryPostProcessor可以操作容器,BeanPostProcessor會(huì)影響所有Bean的生命周期.
  • BeanDefinitionRegistryPostProcessor是一種特殊的BeanFactoryPostProcessor,優(yōu)于其他BeanFactoryPostProcessor執(zhí)行.

擴(kuò)展閱讀

Spring系列六:Spring BeanPostProcessor
談?wù)凷pring中的BeanPostProcessor接口
Spring 執(zhí)行順序:PostProcessor 接口
Spring BeanPostProcessor

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容