国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Springboot擴展點之BeanDefinitionRegistryPostProcessor,你學會了嗎?

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

前言

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

圖片圖片

功能特性

  1. postProcessBeanDefinitionRegistry()方法 可以通過BeanDefinitionRegistry對BeanDefintion進行增刪改查;
  2. 繼承了BeanFactoryPostProcessor,BeanFactoryPostProcessor是容器級別的擴展接口,org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory方法在容器實例化后、刷新容器前被執行,即在容器刷新前還可以對BeanDefintion再作一些操作;
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
   void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
@FunctionalInterface
public interface BeanFactoryPostProcessor {
   void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

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

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

BeanDefinition

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

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

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;
    //根據beanName查詢beanDefinition
   BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;
    //判斷某個beanDefinition是否已經注冊
   boolean containsBeanDefinition(String beanName);
    //獲取所有已注冊的beanDefinition
   String[] getBeanDefinitionNames();
    //獲取所有已注冊的beanDefinition的數量
   int getBeanDefinitionCount();
    //判斷某個beanDefinition是否已經被使用
   boolean isBeanNameInUse(String beanName);


}

ConfigurableListableBeanFactory

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

圖片圖片

自定義實現

MyBeanDefinitionRegistryPostProcessor

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

  1. 在postProcessBeanDefinitionRegistry()方法被調用的時候手工在Spring中注冊了Dog類的BeanDefinition信息;
  2. 在postProcessBeanFactory()方法被調用的時候,從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------------");
        //根據類名取出手工注冊的beanDefinition
        BeanDefinition beanDefinition = beanFactory.getBeanDefinition("dog");
        System.out.println(beanDefinition.getBeanClassName());
        //根據類從容器中取出手工注冊的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());
}

UML類圖

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

圖片圖片

初始化和執行時機

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

  1. 執行項目的主類,SpringApplication#run被調用;
  2. 進入boot.SpringApplication#run方法后,剛開始是一些Spring容器初始化的配置操作,直到執行到SpringApplication#refreshContext,開始容器刷新,進入了關鍵階段;
  3. 在SpringApplication#refreshContext,實際的刷新邏輯是在AbstractApplicationContext#refresh方法中;
  4. AbstractApplicationContext#refresh方法中,調用AbstractApplicationContext#invokeBeanFactoryPostProcessors開始初始化和執行實現BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry()和postProcessBeanFactory();
  5. 進入AbstractApplicationContext#invokeBeanFactoryPostProcessors方法,發現又調用了PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors();
  6. 在PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法中,并不是直接就初始化和執行postProcessBeanDefinitionRegistry()和postProcessBeanFactory(),而是又進行了一系列的判斷,其判斷順序是:1、通過AbstractApplicationContext#addBeanFactoryPostProcessor提前注冊的BeanDefinitionRegistryPostProcessor實現類;2、實現了PriorityOrdered接口;3、是否實現了Ordered;4、剩下的其他BeanDefinitionRegistryPostProcessor實現類;自定義的MyBeanDefinitionRegistryPostProcessor就屬于第4類,所以是所有實現里較晚才被執行的,如果想要提前被執行,可以考慮前面三種方式;
  7. 在PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()方法中執行完MyBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry方法后,緊接著就開始執行MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory方法了;從整個調用過程看postProcessBeanDefinitionRegistry()是早于postProcessBeanFactory()方法執行;

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

圖片圖片

內部實現類

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

總結

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

責任編輯:武曉燕 來源: 凡夫編程
相關推薦

2024-05-29 07:47:30

SpringJava@Resource

2024-08-21 08:27:30

擴展數據庫服務器

2023-03-07 07:50:15

Transactio事務代碼

2023-08-08 08:23:08

Spring日志?線程池

2023-11-29 07:23:04

參數springboto

2024-01-19 08:25:38

死鎖Java通信

2024-02-04 00:00:00

Effect數據組件

2023-07-26 13:11:21

ChatGPT平臺工具

2023-01-10 08:43:15

定義DDD架構

2023-08-01 12:51:18

WebGPT機器學習模型

2024-01-02 12:05:26

Java并發編程

2023-12-08 13:23:00

大數據MySQL存儲

2024-07-31 08:39:45

Git命令暫存區

2024-05-06 00:00:00

InnoDBView隔離

2023-12-12 08:02:10

2023-01-30 09:01:54

圖表指南圖形化

2022-07-08 09:27:48

CSSIFC模型

2024-08-06 09:47:57

2023-10-10 11:04:11

Rust難點內存

2022-07-13 08:16:49

RocketMQRPC日志
點贊
收藏

51CTO技術棧公眾號

精品国产成人av| 欧美视频在线免费| 亚洲一区二区三区香蕉| 91精品一区| 欧美日韩和欧美的一区二区| 日本福利视频| 国产精品午夜免费| 久久精品免费一区二区| 日本成人在线电影网| 91亚洲国产成人精品性色| 欧美爱爱网站| 欧美国产日韩一区二区在线观看| 国产高清中文字幕在线| 91精品中文字幕一区二区三区| 在线欧美成人| 亚洲综合在线免费观看| 在线观看国产一级片| 久久蜜桃av一区二区天堂 | 国产精品福利视频| 欧美激情777| 国产精品色午夜在线观看| 免费观看成人www动漫视频| 欧美成人午夜激情视频| 51亚洲精品| 欧美激情亚洲自拍| av综合网站| 日韩av免费看| 国产伦一区二区三区| 日本欧美精品在线| 欧美日韩第一| www.久久草| 久久黄色网页| 亚洲日本欧美在线| 成人av中文字幕| 天天操天天爱天天爽| 日韩美女啊v在线免费观看| 国产剧情av在线| 精品露脸国产偷人在视频| 天堂v视频永久在线播放| 欧美日韩一区不卡| 狼人综合视频| 欧美裸体xxxx极品少妇| 日韩精品亚洲aⅴ在线影院| 国产精品日韩欧美| 一区二区日韩免费看| 亚洲一区二区精品在线| 成人亚洲精品久久久久软件| av五月天在线| 欧美性生交大片免费| 色呦呦在线播放| 精品国偷自产在线视频| 在线视频亚洲专区| 九色91在线视频| 国产福利精品一区| 老司机在线免费视频| 欧美性猛交xxxxxxxx| а√天堂8资源中文在线| 久久福利视频网| 中文字幕人成人乱码| 中文字幕中文字幕在线中心一区| 久久蜜臀中文字幕| 神马久久高清| 亚洲视屏在线播放| 色88久久久久高潮综合影院| 欧美中日韩免费视频| 91在线国产福利| 青青草免费在线| 中日韩午夜理伦电影免费| 国产日产精品一区二区三区四区的观看方式 | 最色在线观看| 欧美成人高清电影在线| 麻豆久久一区| 国产精品久久亚洲| www..com久久爱| 天堂在线免费av| 在线精品国产成人综合| 五月天综合网站| 日韩黄色短视频| 91国模大尺度私拍在线视频| 网友自拍亚洲| 亚洲一区亚洲二区亚洲三区| 国产激情视频一区二区在线观看 | 国产精品美乳在线观看| 蜜臀av一级做a爰片久久| 成人国产视频在线| 国产午夜精品美女视频明星a级| 国产高清一区| 污视频网站观看| 亚洲裸体xxxx| 欧美色一级片| 一级黄色特级片| 亚洲欧美国产精品久久久久久久| 三级电影一区| 欧洲熟妇精品视频| 亚洲成人精品视频在线观看| 日韩欧美精品一区| 日韩人妻精品无码一区二区三区| 欧美一区二区视频在线观看| 国产欧美日韩在线一区二区| 日本少妇高潮喷水视频| 日韩欧美不卡一区| 亚洲精品网址| caopor在线视频| 精品日韩一区二区三区免费视频| 日本一区二区高清不卡| 北条麻妃在线一区| 日韩毛片在线看| 亚洲综合日本| 久久综合九色综合久| 欧日韩不卡在线视频| 国产精品一区二区视频| 麻豆网站在线| 91在线精品播放| 亚洲自拍偷拍网站| 久久久久观看| 国产精品igao| 在线看片不卡| 日本黄色三级大片| 在线看日韩av| 高清成人免费视频| 丁香花在线观看完整版电影| 精品久久sese| 欧亚洲嫩模精品一区三区| 少妇精品久久久一区二区| 国产小视频精品| 97精品一区二区三区| 中文字幕免费观看一区| 亚洲不卡视频| 拍拍拍999自拍偷| 国内免费精品永久在线视频| 26uuu精品一区二区三区四区在线 26uuu精品一区二区在线观看 | 亚洲天堂一区二区三区| 精品在线视频一区| 成人私拍视频| 日本一道在线观看| 亚洲桃花岛网站| 粉嫩嫩av羞羞动漫久久久 | 天堂av一区二区| 日韩一区二区电影在线| 国产一区91| 国产一线二线在线观看| 日本电影一区二区三区| 日韩欧美在线一区二区三区| 亚洲综合激情| 韩日精品一区二区| www.av中文字幕| 欧美夫妻性生活xx| 亚洲激情第一区| 我不卡手机影院| 欧美成人性生活视频| 日韩欧美视频一区二区| 日韩精品丝袜在线| 2019国产精品| 九九在线精品| 黄色小视频在线观看| 久久一区免费| 亚洲精品黄网在线观看| 处破女av一区二区| 丁香婷婷成人| 久久经典视频| 亚洲午夜精品福利| 久久亚洲精品小早川怜子66| 亚洲欧洲三级电影| 欧美视频二区| 黑人精品一区| 男女午夜视频在线观看| 精品麻豆av| 亚洲激情精品| 嫩草香蕉在线91一二三区| 最近看过的日韩成人| 欧美成在线视频| 天天综合天天综合色| 国产日韩亚洲欧美精品| 在线看片福利| aaa一级毛片| 久久99热只有频精品91密拍| 国产小视频国产精品| 亚洲精品一卡二卡| 久久午夜视频| 国产精品白丝av嫩草影院| 成人欧美亚洲| 国产a级片网站| 成人国产精品久久久| 亚洲国产中文字幕久久网| 中文成人综合网| 日韩亚洲国产精品| 99久久精品一区二区成人| gogogo影视剧免费观看在线观看| 欧美精品一区在线| 久久久久中文字幕| 欧美三级三级三级爽爽爽| 麻豆久久久久久久| 免费成人结看片| 麻豆mv在线看| 黄页网址在线观看| 91免费版看片| 成人网址在线观看| 亚洲男人天堂手机在线| 亚洲美女精品一区| 国产69精品久久777的优势|