最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springboot容器級后置處理器BeanDefinitionRegistryPostProcessor

 更新時間:2023年01月06日 13:59:22   作者:凡夫販夫  
這篇文章主要介紹了Springboot容器級后置處理器BeanDefinitionRegistryPostProcessor,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧

前言

通過這篇文章來大家分享一下,另外一個Springboot的擴展點BeanDefinitionRegistryPostProcessor,一般稱這類擴展點為容器級后置處理器,另外一類是Bean級的后置處理器;容器級的后置處理器會在Spring容器初始化后、刷新前這個時間執(zhí)行一次,Bean級的重置處理器,則是在每一個Bean實例化前后都會執(zhí)行。

1. 功能特性

postProcessBeanDefinitionRegistry()方法可以通過BeanDefinitionRegistry對BeanDefintion進行增刪改查;

繼承了BeanFactoryPostProcessor,BeanFactoryPostProcessor是容器級別的擴展接口,org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory方法在容器實例化后、刷新容器前被執(zhí)行,即在容器刷新前還可以對BeanDefintion再作一些操作;

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
   void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
@FunctionalInterface
public interface BeanFactoryPostProcessor {
   void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

總結(jié)起來就是,在所有的BeanDefinition加載完成之后,Bean真正被實例化之前,可以通過實現(xiàn)BeanDefinitionRegistryPostProcessor接口,對BeanDefinition再做一些定制化的操作,比如修改某個bean的BeanDefinition的屬性、手動注冊一些復(fù)雜的Bean。

對于Spring原理不太熟悉的小伙伴心里看到這可能有點暈了,BeanDefinition是什么?BeanDefinitionRegistry又是什么?ConfigurableListableBeanFactory又又是什么?別著急,這里拐個彎簡單的解釋一下,對整篇文章的理解會更順暢。

1.1 BeanDefinition

大家都知道,Spring的核心之一是IOC(控制反轉(zhuǎn)),Spring之所以可以實現(xiàn)bean控制權(quán)的反轉(zhuǎn),是因為Spring的容器功能,在bean納入Spring容器管理前,所有bean會被抽象封裝成一個BeanDefinition實例,然后會在不同的時機根據(jù)BeanDefinition實例信息對bean進行實例化。

簡單說,Dog.java描述狗這一類動物的屬性和行為,BeanDefinition描述Dog.java這個類。

1.2 BeanDefinitionRegistry

BeanDefinitionRegistry從字面意思看是bean的定義信息的注冊登記,其實這個類的功能和字面意思一樣,就是對BeanDefinition進行管理(增刪改查);

public interface BeanDefinitionRegistry extends AliasRegistry {
    //注冊beanDefinition
   void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
         throws BeanDefinitionStoreException;
    //移除指定的beanDefinition
   void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
    //根據(jù)beanName查詢beanDefinition
   BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
    //判斷某個beanDefinition是否已經(jīng)注冊
   boolean containsBeanDefinition(String beanName);
    //獲取所有已注冊的beanDefinition
   String[] getBeanDefinitionNames();
    //獲取所有已注冊的beanDefinition的數(shù)量
   int getBeanDefinitionCount();
    //判斷某個beanDefinition是否已經(jīng)被使用
   boolean isBeanNameInUse(String beanName);
}

1.3 ConfigurableListableBeanFactory

上面提到了Spring的容器,Spring的核心之一是IOC,那么Spring的容器設(shè)計就是核心中的核心了。Spring的容器有多種形態(tài),最基礎(chǔ)的形態(tài)就是BeanFactory,ConfigurableListableBeanFactory間接繼承了BeanFactory,因此ConfigurableListableBeanFactory實現(xiàn)類除了有Spring基礎(chǔ)版本容器的功能外,還有一些高級的功能,Springboot默認的實際實現(xiàn)是DefaultListableBeanFactory,有興趣的小伙伴可以以此為入口深入探究一番,這里不展開細說了。

2.自定義實現(xiàn)

2.1 MyBeanDefinitionRegistryPostProcessor

下面通過一個具體類MyBeanDefinitionRegistryPostProcessor實現(xiàn)BeanDefinitionRegistryPostProcessor接口,來探究BeanDefinitionRegistryPostProcessor實現(xiàn)類的初始化和執(zhí)行過程。

  • 在postProcessBeanDefinitionRegistry()方法被調(diào)用的時候手工在Spring中注冊了Dog類的BeanDefinition信息;
  • 在postProcessBeanFactory()方法被調(diào)用的時候,從Spring容器中取出Dog類的BeanDefinition信息和Dog類的實例;
@Data
public class Dog {
    private String name;
    private String color;
}
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        //手工定義一個beanDefinition實例
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        //給beanDefinition填充屬性
        beanDefinition.setBeanClass(Dog.class);
        MutablePropertyValues propertyValues = new MutablePropertyValues();
        PropertyValue propertyValue1 = new PropertyValue("name", "旺財");
        PropertyValue propertyValue2 = new PropertyValue("color", "黑色");
        propertyValues.addPropertyValue(propertyValue1);
        propertyValues.addPropertyValue(propertyValue2);
        beanDefinition.setPropertyValues(propertyValues);
        //注冊手工定義的beanDefinition
        registry.registerBeanDefinition("dog", beanDefinition);
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("-----------start------------");
        //根據(jù)類名取出手工注冊的beanDefinition
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("dog");
        System.out.println(beanDefinition.getBeanClassName());
        //根據(jù)類從容器中取出手工注冊的beanDefinition所描述的實例bean
        Dog dog = beanFactory.getBean(Dog.class);
        System.out.println(dog.getName());
        System.out.println(dog.getColor());
        System.out.println("-----------end------------");
    }
}

單元測試

@Test
public void test(){
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext("com.fanfu");
    Dog dog = ((Dog) context.getBean("dog"));
    System.out.println(dog.getName());
    System.out.println(dog.getColor());
}

2.2 UML類圖

通過BeanDefinitionRegistryPostProcessorUML類圖可以看出BeanDefinitionRegistryPostProcessor繼承了BeanFactoryPostProcessor,postProcessBeanDefinitionRegistry()方法屬于BeanDefinitionRegistryPostProcessor,postProcessBeanFactory()屬于BeanFactoryPostProcessor,所有實現(xiàn)了BeanDefinitionRegistryPostProcessor接口的實現(xiàn)類都需要實現(xiàn)這兩個方法,而作為Springboot的擴展點之一,其擴展的邏輯也在這兩個方法中。

3. 初始化和執(zhí)行時機

通過自定義的MyBeanDefinitionRegistryPostProcessor類,實現(xiàn)BeanDefinitionRegistryPostProcessor接口,從項目啟動開始,其執(zhí)行過程如下:

  • 執(zhí)行項目的主類,org.springframework.boot.SpringApplication#run被調(diào)用;
  • 進入boot.SpringApplication#run方法后,剛開始是一些Spring容器初始化的配置操作,直到執(zhí)行到org.springframework.boot.SpringApplication#refreshContext,開始容器刷新,進入了關(guān)鍵階段;
  • 在SpringApplication#refreshContext,實際的刷新邏輯是在org.springframework.context.support.AbstractApplicationContext#refresh方法中;
  • AbstractApplicationContext#refresh方法中,調(diào)用org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors開始初始化和執(zhí)行實現(xiàn)BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry()和postProcessBeanFactory();
  • 進入AbstractApplicationContext#invokeBeanFactoryPostProcessors方法,發(fā)現(xiàn)又調(diào)用了org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors();
  • 在PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法中,并不是直接就初始化和執(zhí)行postProcessBeanDefinitionRegistry()和postProcessBeanFactory(),而是又進行了一系列的判斷,其判斷順序是:

1、通過AbstractApplicationContext#addBeanFactoryPostProcessor提前注冊的BeanDefinitionRegistryPostProcessor實現(xiàn)類;

2、實現(xiàn)了PriorityOrdered接口;

3、是否實現(xiàn)了Ordered;

4、剩下的其他BeanDefinitionRegistryPostProcessor實現(xiàn)類;自定義的MyBeanDefinitionRegistryPostProcessor就屬于第4類,所以是所有實現(xiàn)里較晚才被執(zhí)行的,如果想要提前被執(zhí)行,可以考慮前面三種方式;

  • 在PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法中執(zhí)行完MyBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry方法后,緊接著就開始執(zhí)行MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory方法了;從整個調(diào)用過程看postProcessBeanDefinitionRegistry()是早于postProcessBeanFactory()方法執(zhí)行;

下面是我根據(jù)整個調(diào)用過程畫的一個時序圖,過程確實比較復(fù)雜,但是邏輯比較清晰,因此并不難理解,想要真的搞清楚整個過程,最好的方法就是照著這個圖,親自執(zhí)行一遍,通過debug觀察每一個關(guān)鍵節(jié)點的執(zhí)行過程。

4. 內(nèi)部實現(xiàn)類

spring-boot-starter-web中內(nèi)置的實現(xiàn)類有CachingMetadataReaderFactoryPostProcessor、ConfigurationClassPostProcessor、ConfigurationWarningsPostProcessor、EmbeddedDataSourceBeanFactoryPostProcessor、ImportsCleanupPostProcessor、TestRestTemplateRegistrar、WebTestClientRegistrar、WsdlDefinitionBeanFactoryPostProcessor,觀察一下每個實現(xiàn)類會發(fā)現(xiàn):都比較類似,這些內(nèi)置實現(xiàn)類都是Springboot中的內(nèi)部類,通過這些BeanDefinitionRegistryPostProcessor內(nèi)部實現(xiàn)類向Spring容器中注冊了一些特殊的BeanDefinition,如果展開詳細再說一說這些Bean,怕是一天一夜也說不完,有興趣的小伙伴可以深入了解一下,這里就不再展開了。

5. 總結(jié)

通過梳理整個過程,其實最關(guān)鍵的就是一句話:在Spring容器初始后、未刷新前,即Bean已被掃描注冊為BeanDefinition后,未正式實例化前,可以通過實現(xiàn)BeanDefinitionRegistryPostProcessor做一些額外的操作。

到此這篇關(guān)于Springboot容器級后置處理器BeanDefinitionRegistryPostProcessor的文章就介紹到這了,更多相關(guān)Springboot BeanDefinitionRegistryPostProcessor內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java中類的加載順序執(zhí)行結(jié)果

    Java中類的加載順序執(zhí)行結(jié)果

    這篇文章主要介紹了Java中類的加載順序執(zhí)行結(jié)果的相關(guān)資料,需要的朋友可以參考下
    2017-10-10
  • Java以struts2為例介紹如何實現(xiàn)圖片上傳

    Java以struts2為例介紹如何實現(xiàn)圖片上傳

    這篇文章主要介紹了Java struts2中如何實現(xiàn)圖片上傳的相關(guān)資料,需要的朋友可以參考下
    2015-11-11
  • Maven使用方法詳及方式詳細介紹

    Maven使用方法詳及方式詳細介紹

    使用maven倉庫的話需要從網(wǎng)上下載maven的包,比如“apache-maven-3.5.4-bin.tar”,下載完成之后解壓,在解壓的文件夾中的conf目錄下的settings.xml文件夾下就可以配置maven遠程倉庫和本地倉庫的地址
    2022-11-11
  • Mybatis-Plus條件構(gòu)造器select方法返回指定字段方式

    Mybatis-Plus條件構(gòu)造器select方法返回指定字段方式

    這篇文章主要介紹了Mybatis-Plus條件構(gòu)造器select方法返回指定字段方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • SpringBoot配置攔截器實現(xiàn)過程詳解

    SpringBoot配置攔截器實現(xiàn)過程詳解

    在系統(tǒng)中經(jīng)常需要在處理用戶請求之前和之后執(zhí)行一些行為,例如檢測用戶的權(quán)限,或者將請求的信息記錄到日志中,即平時所說的"權(quán)限檢測"及"日志記錄",下面這篇文章主要給大家介紹了關(guān)于在SpringBoot項目中整合攔截器的相關(guān)資料,需要的朋友可以參考下
    2022-10-10
  • 輕松掌握Java注解,讓編程更智能、更優(yōu)雅

    輕松掌握Java注解,讓編程更智能、更優(yōu)雅

    輕松掌握Java注解?沒問題!想要讓你的Java代碼更具可讀性、維護性,同時提升開發(fā)效率?本指南將帶你快速入門Java注解的世界,只需短短幾分鐘,你就能揭秘這個強大的編程工具,讓編寫有聲明性邏輯的代碼變得輕而易舉,趕快一起來探索吧!
    2024-01-01
  • Spring Boot的Maven插件Spring Boot Maven plugin詳解

    Spring Boot的Maven插件Spring Boot Maven plu

    Spring Boot的Maven插件Spring Boot Maven plugin以Maven的方式提供Spring Boot支持,Spring Boot Maven plugin將Spring Boot應(yīng)用打包為可執(zhí)行的jar或war文件,然后以通常的方式運行Spring Boot應(yīng)用,本文介紹Spring Boot的Maven插件Spring Boot Maven plugin,一起看看吧
    2024-01-01
  • java計算任意位水仙花數(shù)示例(回文數(shù))

    java計算任意位水仙花數(shù)示例(回文數(shù))

    這篇文章主要介紹了java計算任意位水仙花數(shù)示例(回文數(shù)),需要的朋友可以參考下
    2014-05-05
  • SpringMVC中文件的上傳與下載詳細解析

    SpringMVC中文件的上傳與下載詳細解析

    這篇文章主要介紹了SpringMVC中文件的上傳與下載詳細解析,在開發(fā)中有遇到文件上傳下載的功能需求,今天就來說一下前后端的實現(xiàn)和要注意的地方,需要的朋友可以參考下
    2024-01-01
  • Java Spring @Autowired的這些騷操作,你都知道嗎

    Java Spring @Autowired的這些騷操作,你都知道嗎

    這篇文章主要介紹了徹底搞明白Spring中的自動裝配和Autowired注解的使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2021-09-09

最新評論

南开区| 南和县| 凉城县| 博罗县| 琼中| 垫江县| 玉树县| 广州市| 邢台市| 鄱阳县| 和静县| 安达市| 桐柏县| 禄劝| 保靖县| 巴塘县| 渭源县| 金湖县| 滨海县| 尉氏县| 图木舒克市| 元阳县| 兰溪市| 祁东县| 宜阳县| 方城县| 磴口县| 镇宁| 隆德县| 南川市| 竹山县| 航空| 忻城县| 弋阳县| 尚义县| 苍溪县| 正镶白旗| 天峻县| 肇源县| 陆河县| 贵州省|