日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線(xiàn)咨詢(xún)客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

前言

通過(guò)這篇文章來(lái)大家分享一下,另外一個(gè)Springboot的擴(kuò)展點(diǎn)BeanDefinitionRegistryPostProcessor,一般稱(chēng)這類(lèi)擴(kuò)展點(diǎn)為容器級(jí)后置處理器,另外一類(lèi)是Bean級(jí)的后置處理器;容器級(jí)的后置處理器會(huì)在Spring容器初始化后、刷新前這個(gè)時(shí)間執(zhí)行一次,Bean級(jí)的后置處理器,則是在每一個(gè)Bean實(shí)例化前后都會(huì)執(zhí)行。

Springboot擴(kuò)展點(diǎn)之BeanDefinitionRegistryPostProcessor,你學(xué)會(huì)了嗎?

功能特性

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

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

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

BeanDefinition

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

簡(jiǎn)單說(shuō),Dog.JAVA描述狗這一類(lèi)動(dòng)物的屬性和行為,BeanDefinition描述Dog.java這個(gè)類(lèi)。

BeanDefinitionRegistry

BeanDefinitionRegistry從字面意思看是bean的定義信息的注冊(cè)登記,其實(shí)這個(gè)類(lèi)的功能和字面意思一樣,就是對(duì)BeanDefinition進(jìn)行管理(增刪改查);

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


}

ConfigurableListableBeanFactory

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

Springboot擴(kuò)展點(diǎn)之BeanDefinitionRegistryPostProcessor,你學(xué)會(huì)了嗎?

自定義實(shí)現(xiàn)

MyBeanDefinitionRegistryPostProcessor

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

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

單元測(cè)試

@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類(lèi)圖

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

Springboot擴(kuò)展點(diǎn)之BeanDefinitionRegistryPostProcessor,你學(xué)會(huì)了嗎?

初始化和執(zhí)行時(shí)機(jī)

通過(guò)自定義的MyBeanDefinitionRegistryPostProcessor類(lèi),實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor接口,從項(xiàng)目啟動(dòng)開(kāi)始,其執(zhí)行過(guò)程如下:

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

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

Springboot擴(kuò)展點(diǎn)之BeanDefinitionRegistryPostProcessor,你學(xué)會(huì)了嗎?

內(nèi)部實(shí)現(xiàn)類(lèi)

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

總結(jié)

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

分享到:
標(biāo)簽:Springboot
用戶(hù)無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定