一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術(shù)及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Spring的BeanFactoryPostProcessor接口示例代碼詳解

Spring的BeanFactoryPostProcessor接口示例代碼詳解

2021-08-13 11:36程序員自由之路 Java教程

這篇文章主要介紹了Spring的BeanFactoryPostProcessor接口,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

接口簡介

BeanFactoryPostProcessor 接口是 Spring 初始化 BeanFactory 時對外暴露的擴展點,Spring IoC 容器允許 BeanFactoryPostProcessor 在容器實例化任何 bean 之前讀取 bean 的定義,并可以修改它。

BeanDefinitionRegistryPostProcessor 繼承自 BeanFactoryPostProcessor,比 BeanFactoryPostProcessor 具有更高的優(yōu)先級,主要用來在常規(guī)的 BeanFactoryPostProcessor 檢測開始之前注冊其他 bean 定義。特別是,你可以通過 BeanDefinitionRegistryPostProcessor 來注冊一些常規(guī)的 BeanFactoryPostProcessor,因為此時所有常規(guī)的 BeanFactoryPostProcessor 都還沒開始被處理。

Spring的BeanFactoryPostProcessor接口示例代碼詳解

注意點:通過BeanDefinitionRegistryPostProcessor 注冊的 BeanDefinitionRegistryPostProcessor 接口的postProcessBeanDefinitionRegistry方法將得不到調(diào)用,具體的原因會在下面的代碼中解釋。

BeanFactoryPostProcessor 接口調(diào)用機制

BeanFactoryPostProcessor 接口的調(diào)用在 AbstractApplicationContext#invokeBeanFactoryPostProcessors方法中。

?
1
2
3
4
5
6
7
8
9
10
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
 
        // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
        // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
        if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }
    }

進入PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors())方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
   // 用于存放已經(jīng)處理過的Bean名字
        Set<String> processedBeans = new HashSet<>();
   // 一般會進入這個判斷
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
    // 所謂的regularPostProcessors就是指實現(xiàn)BeanFactoryPostProcessor接口的Bean
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
    // 所謂的registryProcessors就是指實現(xiàn)BeanDefinitionRegistryPostProcessor接口的Bean
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
    // 這邊遍歷的是通過ApplicationContext接口注冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口
    // 需要和BeanFactory中BeanDefinitionMap中的BeanFactoryPostProcessor接口區(qū)分開
            for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
                if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                    BeanDefinitionRegistryPostProcessor registryProcessor =
                            (BeanDefinitionRegistryPostProcessor) postProcessor;
      //如果是BeanDefinitionRegistryPostProcessor,則先進行postProcessBeanDefinitionRegistry處理,這個方法一般進行BeanDefinition注冊,從這邊可以看出BeanDefinitionRegistryPostProcessor接口的方法先調(diào)用,所以優(yōu)先級高于BeanFactoryPostProcessor
      // 通過這個代碼可以看出,通過ApplicationContext直接注冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor并不支持Order接口,而是根據(jù)注冊的順序執(zhí)行
                    registryProcessor.postProcessBeanDefinitionRegistry(registry);
      // 保存這個BeanDefinitionRegistryPostProcessor,因為還要執(zhí)行這個類的BeanFactoryPostProcessor方法;
                    registryProcessors.add(registryProcessor);
                }
                else {
      // 保存,后面還要執(zhí)行這個類的BeanFactoryPostProcessor方法;
                    regularPostProcessors.add(postProcessor);
                }
            }
 
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
    // 這邊獲取的是BeanFactory中的BeanDefinitionRegistryPostProcessor
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
     //先處理PriorityOrdered標注的BeanDefinitionRegistryPostProcessor
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
      //將其標記為已經(jīng)處理,防止重復處理
                    processedBeans.add(ppName);
                }
            }
    // 將其排序,以便按順序處理
            sortPostProcessors(currentRegistryProcessors, beanFactory);
    // 將其保存,以便處理這個類的BeanFactoryPostProcessor方法
            registryProcessors.addAll(currentRegistryProcessors);
    // 執(zhí)行BeanDefinitionRegistryPostProcessor接口方法
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
    // 清除,以便開始處理@Order標注的注解
            currentRegistryProcessors.clear();
  
    // 注意:這邊重新獲取BeanDefinitionRegistryPostProcessor是有深意的,因為上面在處理@PriorityOrdered標注的BeanDefinitionRegistryPostProcessor時可能又注入了新的BeanDefinitionRegistryPostProcessor。
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
     // 判斷是否處理過,防止重復處理,下面的邏輯和上面相同, 不介紹了
                if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
 
    // 處理不標注注解的BeanDefinitionRegistryPostProcessor
            boolean reiterate = true;
            while (reiterate) {
                reiterate = false;
                postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
                for (String ppName : postProcessorNames) {
                    if (!processedBeans.contains(ppName)) {
                        currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                        processedBeans.add(ppName);
                        reiterate = true;
                    }
                }
                sortPostProcessors(currentRegistryProcessors, beanFactory);
                registryProcessors.addAll(currentRegistryProcessors);
                invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
                currentRegistryProcessors.clear();
            }
 
            // 調(diào)用postProcessBeanFactory 方法,所以BeanDefinitionRegistryPostProcessor中的postProcessBeanFactory方法的優(yōu)先級要高。
            invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
            invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
        }
 
        else {
            // Invoke factory processors registered with the context instance.
            invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
        }
 
        // 開始處理BeanFactoryPostProcessor接口
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
 
        // 也是按照@PriorityOrdered @Ordered 和普通的方式進行處理
        List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
        List<String> orderedPostProcessorNames = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        for (String ppName : postProcessorNames) {
    // 可能已經(jīng)處理過
            if (processedBeans.contains(ppName)) {
                // skip - already processed in first phase above
            }
            else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
            }
            else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                orderedPostProcessorNames.add(ppName);
            }
            else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }
   // 先執(zhí)行@PriorityOrdered標注的接口
        sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
   // 處理@Order標注的類
        List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
        for (String postProcessorName : orderedPostProcessorNames) {
    // 這邊通過名字重新拿了Bean,應該是怕上面的處理改變了Bean
            orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        sortPostProcessors(orderedPostProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
 
        // 最后調(diào)用普通的BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
        for (String postProcessorName : nonOrderedPostProcessorNames) {
            nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
        }
        invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
 
        // Clear cached merged bean definitions since the post-processors might have
        // modified the original metadata, e.g. replacing placeholders in values...
        beanFactory.clearMetadataCache();
    }

簡單總結(jié)

上面的方法看起來很長很復雜,但其實干的事情并不多,就調(diào)用了BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口的實現(xiàn)。這邊再簡單總結(jié)下具體的過程:

step1:執(zhí)行通過ApplicationContext#addBeanFactoryPostProcessor()方法注冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor。

具體過程如下:假如通過ApplicationContext注冊了一個BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor,那么會先執(zhí)行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,但是BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法和BeanFactoryPostProcessor的postProcessBeanFactory方法暫時都不會在這步執(zhí)行。

另外需要注意的是:通過ApplicationContext注冊的BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor都不支持@PriorityOrdered和@Ordered順序處理,而是按照我們添加的順序處理

step2:處理BeanFactory中的BeanDefinitionRegistryPostProcessor,處理的順序是先處理@PriorityOrdered標注的,再處理@Ordered標注的,最后處理普通的BeanDefinitionRegistryPostProcessor。到這邊,所有BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法都已經(jīng)調(diào)用完畢,下面就開始處理BeanFactoryPostProcessor的postProcessBeanFactory方法。

step3:調(diào)用BeanDefinitionRegistryPostProcessor實現(xiàn)的postProcessBeanFactory方法(因為BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口)

step4:調(diào)用通過ApplicationContext#addBeanFactoryPostProcessor()注冊的“單純”的BeanFactoryPostProcessor

step5:調(diào)用BeanFactory中的BeanFactoryPostProcessor,調(diào)用順序也是按照@PriorityOrdered和@Ordered順序處理,沒有這兩個注解的最后處理。

好了,到這邊BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor接口就已經(jīng)處理完了。后面我們會拿ConfigurationClassPostProcessor 這個特殊的BeanDefinitionRegistryPostProcessor做列子講下具體流程,這邊只是介紹BeanFactoryPostProcessor的調(diào)用機制。

到此這篇關(guān)于Spring的BeanFactoryPostProcessor接口的文章就介紹到這了,更多相關(guān)Spring BeanFactoryPostProcessor接口內(nèi)容請搜索服務器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務器之家!

原文鏈接:https://www.cnblogs.com/54chensongxia/p/14430353.html

延伸 · 閱讀

精彩推薦
  • Java教程每日六道java新手入門面試題,通往自由的道路第二天

    每日六道java新手入門面試題,通往自由的道路第二天

    這篇文章主要為大家分享了最有價值的6道java面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,對hashCode方法的設計、垃圾收集...

    太子爺哪吒6222021-09-23
  • Java教程Java之SpringBoot集成ActiveMQ消息中間件案例講解

    Java之SpringBoot集成ActiveMQ消息中間件案例講解

    這篇文章主要介紹了Java之SpringBoot集成ActiveMQ消息中間件案例講解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可...

    愚蠢的土撥鼠~10402021-10-29
  • Java教程java字符串求并集的方法

    java字符串求并集的方法

    這篇文章主要介紹了java字符串求并集的方法,涉及Java字符串操作中union方法的使用,是Java字符串操作中非常實用的基本技巧,需要的朋友可以參考下 ...

    shichen20146552019-12-06
  • Java教程Java基礎知識匯總

    Java基礎知識匯總

    這篇文章對Java編程語言的基礎知識作了一個較為全面的匯總,在這里給大家分享一下。需要的朋友可以參考。...

    李子園的夢想5212021-01-06
  • Java教程java設計模式之外觀模式學習筆記

    java設計模式之外觀模式學習筆記

    這篇文章主要為大家詳細介紹了java設計模式之外觀模式學習筆記,具有一定的參考價值,感興趣的小伙伴們可以參考一下 ...

    翡青2392020-06-24
  • Java教程Java源碼解析阻塞隊列ArrayBlockingQueue介紹

    Java源碼解析阻塞隊列ArrayBlockingQueue介紹

    今天小編就為大家分享一篇關(guān)于Java源碼解析阻塞隊列ArrayBlockingQueue介紹,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起...

    李燦輝9012021-06-30
  • Java教程淺談javap命令拆解字節(jié)碼文件

    淺談javap命令拆解字節(jié)碼文件

    這篇文章主要介紹了拆解字節(jié)碼文件javap命令,對反編譯感興趣的同學可以參考下...

    2048102410422021-09-02
  • Java教程Java中Lambda表達式的進化之路詳解

    Java中Lambda表達式的進化之路詳解

    本文通過示例大家給大家介紹了Java中Lambda表達式的進化之路,感興趣的的朋友一起看看吧,希望能夠給你帶來幫助...

    Thales_ZeeWay4512022-03-10
主站蜘蛛池模板: 无遮掩60分钟从头啪到尾 | 国产综合成人久久大片91 | 成人精品第一区二区三区 | 国产日韩高清一区二区三区 | 欧美成人aa | 亚洲六月丁香婷婷综合 | 欧美特欧美特级一片 | 日日操天天射 | 欧美亚洲另类在线观看 | 国产精品林美惠子在线观看 | ts视频在线观看 | 日本偷偷操 | 日本草草视频 | 息与子中文字幕bd | 国产福利在线观看永久视频 | 日本视频在线免费看 | 国产成人啪精品午夜在线播放 | 天天操天天射天天爽 | 亚洲男人天堂久久 | 欧美国产在线 | 精品国产福利一区二区在线 | 成3d漫二区三区四区 | 免费国产一级观看完整版 | 久久天堂成人影院 | 国产一区二区三区久久精品 | 日韩妹妹 | 国产特黄一级一片免费 | 欧美3d怪物交videos网站 | 亚洲欧美日韩国产精品一区 | 奇米小说 | 日韩一级片在线观看 | 国产主播99 | 国产成+人+综合+亚洲不卡 | 日韩精品成人免费观看 | 国内精品自产拍在线观看91 | 国产成年人在线观看 | 青苹果乐园影院在线播放 | 日本在线视频免费观看 | 人人爽人人香蕉 | 调教车文 | 99久久久久国产 |