Spring IoC源碼學習:invokeBeanFactoryPostProcessors 詳解

目錄

Spring IoC源碼學習全系列

前言

概述

正文

invokeBeanFactoryPostProcessors

代碼塊1:getBeanFactoryPostProcessors

代碼塊2:invokeBeanFactoryPostProcessors

代碼塊3:sortPostProcessors

基本使用

1.BeanDefinitionRegistryPostProcessor 的擴展使用

2.BeanFactoryPostProcessor 的擴展使用

總結

相關文章


Spring IoC源碼學習全系列

小白也看得懂的 Spring IoC 核心流程介紹

Spring IoC源碼學習:總覽

Spring IoC源碼學習:ApplicationContext 刷新前的配置

Spring IoC源碼學習:obtainFreshBeanFactory詳解

Spring IoC源碼學習:parseDefaultElement詳解

Spring IoC源碼學習:parseCustomElement詳解

Spring IoC源碼學習:obtainFreshBeanFactory詳解

Spring IoC源碼學習:invokeBeanFactoryPostProcessors詳解

Spring IoC源碼學習:registerBeanPostProcessors詳解

Spring IoC源碼學習:finishBeanFactoryInitialization詳解

Spring IoC源碼學習:getBean詳解

Spring IoC源碼學習:createBean詳解(上)

Spring IoC源碼學習:createBean詳解(下)

Spring IoC源碼學習:@Autowire 詳解

Spring IoC源碼學習:finishRefresh 詳解

 

前言

隨着 Spring IoC:context:component-scan節點解析 的結束,obtainFreshBeanFactory 方法的解析也告一段落,我們通過5篇文章,完整的介紹了obtainFreshBeanFactory 方法。本文將介紹 obtainFreshBeanFactory 方法之後的另一個重要方法——invokeBeanFactoryPostProcessors。

 

概述

本方法會實例化和調用所有 BeanFactoryPostProcessor(包括其子類 BeanDefinitionRegistryPostProcessor)。

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

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

注:這邊的 “常規 BeanFactoryPostProcessor” 主要用來跟 BeanDefinitionRegistryPostProcessor 區分。

 

正文

首先我們回到 AbstractApplicationContext.refresh() 方法,找到代碼:invokeBeanFactoryPostProcessors(beanFactory) ,單擊該行代碼跳轉到具體的實現。

 

invokeBeanFactoryPostProcessors

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 1.getBeanFactoryPostProcessors(): 拿到當前應用上下文beanFactoryPostProcessors變量中的值
    // 2.invokeBeanFactoryPostProcessors: 實例化並調用所有已註冊的BeanFactoryPostProcessor
    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()));
    }
}

1.拿到當前應用上下文 beanFactoryPostProcessors 變量中的值,見代碼塊1詳解

2.實例化並調用所有已註冊的 BeanFactoryPostProcessor,見代碼塊2詳解

 

代碼塊1:getBeanFactoryPostProcessors

public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
    return this.beanFactoryPostProcessors;
}

這邊 getBeanFactoryPostProcessors() 會拿到當前應用上下文中已經註冊的 BeanFactoryPostProcessor,在默認情況下,this.beanFactoryPostProcessors 是返回空的。

如何添加自定義 BeanFactoryPostProcessor 到 this.beanFactoryPostProcessors 變量中了?

如果還有印象的話,我們在 Spring IoC:refresh前的環境準備 中的代碼塊12介紹過 customizeContext 方法,該方法是 Spring 提供給開發者的一個擴展點,用於自定義應用上下文,並且在 refresh() 方法前就被調用。在這邊就可以通過該方法來添加自定義的 BeanFactoryPostProcessor。

簡單的實現如下:

1.新建一個 ApplicationContextInitializer 的實現類 SpringApplicationContextInitializer ,並在 initialize 方法中寫我們的邏輯。

package com.joonwhee.open.demo.spring;

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @author joonwhee
 * @date 2019/1/19
 */
public class SpringApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        FirstBeanDefinitionRegistryPostProcessor firstBeanDefinitionRegistryPostProcessor = new FirstBeanDefinitionRegistryPostProcessor();
        // 將自定義的firstBeanDefinitionRegistryPostProcessor添加到應用上下文中
        applicationContext.addBeanFactoryPostProcessor(firstBeanDefinitionRegistryPostProcessor);
        // ...自定義操作
        System.out.println("SpringApplicationContextInitializer#initialize");
    }
}

2.將 SpringApplicationContextInitializer 作爲初始化參數 contextInitializerClasses 配置到 web.xml 中。

<context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>
        com.joonwhee.open.demo.spring.SpringApplicationContextInitializer
    </param-value>
</context-param>

這樣,在啓動應用時,FirstBeanDefinitionRegistryPostProcessor 就會被添加到 this.beanFactoryPostProcessors 中。

 

代碼塊2:invokeBeanFactoryPostProcessors

public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    Set<String> processedBeans = new HashSet<String>();

    // 1.判斷beanFactory是否爲BeanDefinitionRegistry,beanFactory爲DefaultListableBeanFactory,
    // 而DefaultListableBeanFactory實現了BeanDefinitionRegistry接口,因此這邊爲true
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        // 用於存放普通的BeanFactoryPostProcessor
        List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
        // 用於存放BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();

        // 2.首先處理入參中的beanFactoryPostProcessors
        // 遍歷所有的beanFactoryPostProcessors, 將BeanDefinitionRegistryPostProcessor和普通BeanFactoryPostProcessor區分開
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                // 2.1 如果是BeanDefinitionRegistryPostProcessor
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                // 2.1.1 直接執行BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                // 2.1.2 添加到registryProcessors(用於最後執行postProcessBeanFactory方法)
                registryProcessors.add(registryProcessor);
            } else {
                // 2.2 否則,只是普通的BeanFactoryPostProcessor
                // 2.2.1 添加到regularPostProcessors(用於最後執行postProcessBeanFactory方法)
                regularPostProcessors.add(postProcessor);
            }
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        // Separate between BeanDefinitionRegistryPostProcessors that implement
        // PriorityOrdered, Ordered, and the rest.
        // 用於保存本次要執行的BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();

        // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
        // 3.調用所有實現PriorityOrdered接口的BeanDefinitionRegistryPostProcessor實現類
        // 3.1 找出所有實現BeanDefinitionRegistryPostProcessor接口的Bean的beanName
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        // 3.2 遍歷postProcessorNames
        for (String ppName : postProcessorNames) {
            // 3.3 校驗是否實現了PriorityOrdered接口
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                // 3.4 獲取ppName對應的bean實例, 添加到currentRegistryProcessors中,
                // beanFactory.getBean: 這邊getBean方法會觸發創建ppName對應的bean對象, 目前暫不深入解析
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                // 3.5 將要被執行的加入processedBeans,避免後續重複執行
                processedBeans.add(ppName);
            }
        }
        // 3.6 進行排序(根據是否實現PriorityOrdered、Ordered接口和order值來排序)
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        // 3.7 添加到registryProcessors(用於最後執行postProcessBeanFactory方法)
        registryProcessors.addAll(currentRegistryProcessors);
        // 3.8 遍歷currentRegistryProcessors, 執行postProcessBeanDefinitionRegistry方法
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        // 3.9 執行完畢後, 清空currentRegistryProcessors
        currentRegistryProcessors.clear();

        // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
        // 4.調用所有實現了Ordered接口的BeanDefinitionRegistryPostProcessor實現類(過程跟上面的步驟3基本一樣)
        // 4.1 找出所有實現BeanDefinitionRegistryPostProcessor接口的類, 這邊重複查找是因爲執行完上面的BeanDefinitionRegistryPostProcessor,
        // 可能會新增了其他的BeanDefinitionRegistryPostProcessor, 因此需要重新查找
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            // 校驗是否實現了Ordered接口,並且還未執行過
            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);
        // 4.2 遍歷currentRegistryProcessors, 執行postProcessBeanDefinitionRegistry方法
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        currentRegistryProcessors.clear();

        // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
        // 5.最後, 調用所有剩下的BeanDefinitionRegistryPostProcessors
        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
            // 5.1 找出所有實現BeanDefinitionRegistryPostProcessor接口的類
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                // 5.2 跳過已經執行過的
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    // 5.3 如果有BeanDefinitionRegistryPostProcessor被執行, 則有可能會產生新的BeanDefinitionRegistryPostProcessor,
                    // 因此這邊將reiterate賦值爲true, 代表需要再循環查找一次
                    reiterate = true;
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            // 5.4 遍歷currentRegistryProcessors, 執行postProcessBeanDefinitionRegistry方法
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
        }

        // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
        // 6.調用所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法(BeanDefinitionRegistryPostProcessor繼承自BeanFactoryPostProcessor)
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        // 7.最後, 調用入參beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的postProcessBeanFactory方法
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    } else {
        // Invoke factory processors registered with the context instance.
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // 到這裏 , 入參beanFactoryPostProcessors和容器中的所有BeanDefinitionRegistryPostProcessor已經全部處理完畢,
    // 下面開始處理容器中的所有BeanFactoryPostProcessor

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    // 8.找出所有實現BeanFactoryPostProcessor接口的類
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    // 用於存放實現了PriorityOrdered接口的BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    // 用於存放實現了Ordered接口的BeanFactoryPostProcessor的beanName
    List<String> orderedPostProcessorNames = new ArrayList<String>();
    // 用於存放普通BeanFactoryPostProcessor的beanName
    List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
    // 8.1 遍歷postProcessorNames, 將BeanFactoryPostProcessor按實現PriorityOrdered、實現Ordered接口、普通三種區分開
    for (String ppName : postProcessorNames) {
        // 8.2 跳過已經執行過的
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
        } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 8.3 添加實現了PriorityOrdered接口的BeanFactoryPostProcessor
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            // 8.4 添加實現了Ordered接口的BeanFactoryPostProcessor的beanName
            orderedPostProcessorNames.add(ppName);
        } else {
            // 8.5 添加剩下的普通BeanFactoryPostProcessor的beanName
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    // 9.調用所有實現PriorityOrdered接口的BeanFactoryPostProcessor
    // 9.1 對priorityOrderedPostProcessors排序
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // 9.2 遍歷priorityOrderedPostProcessors, 執行postProcessBeanFactory方法
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    // 10.調用所有實現Ordered接口的BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    for (String postProcessorName : orderedPostProcessorNames) {
        // 10.1 獲取postProcessorName對應的bean實例, 添加到orderedPostProcessors, 準備執行
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    // 10.2 對orderedPostProcessors排序
    sortPostProcessors(orderedPostProcessors, beanFactory);
    // 10.3 遍歷orderedPostProcessors, 執行postProcessBeanFactory方法
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // Finally, invoke all other BeanFactoryPostProcessors.
    // 11.調用所有剩下的BeanFactoryPostProcessor
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanFactoryPostProcessor>();
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        // 11.1 獲取postProcessorName對應的bean實例, 添加到nonOrderedPostProcessors, 準備執行
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    // 11.2 遍歷nonOrderedPostProcessors, 執行postProcessBeanFactory方法
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values...
    // 12.清除元數據緩存(mergedBeanDefinitions、allBeanNamesByType、singletonBeanNamesByType),
    // 因爲後處理器可能已經修改了原始元數據,例如, 替換值中的佔位符...
    beanFactory.clearMetadataCache();
}

1.判斷 beanFactory 是否爲 BeanDefinitionRegistry。beanFactory 是在之前的 obtainFreshBeanFactory 方法構建的,具體代碼在:AbstractRefreshableApplicationContext.refreshBeanFactory() 方法,代碼如下。

@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        // 創建一個新的BeanFactory
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

可以看出,我們構建的 beanFactory 是一個 DefaultListableBeanFactory ,而 DefaultListableBeanFactory 實現了BeanDefinitionRegistry 接口,因此 beanFactory instanceof BeanDefinitionRegistry 結果爲 true。

3.4 獲取 ppName 對應的 bean 實例,添加到 currentRegistryProcessors 中,準備執行。beanFactory.getBean 方法會觸發創建 ppName 對應的 bean 實例對象,創建 bean 實例是 IoC 的另一個核心內容,之後會單獨解析,目前暫不深入解析。

3.6 進行排序,該方法在下面也被調用了好幾次,見代碼塊3詳解。

 

代碼塊3:sortPostProcessors

private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    Comparator<Object> comparatorToUse = null;
    if (beanFactory instanceof DefaultListableBeanFactory) {
        // 1.獲取設置的比較器
        comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
    }
    if (comparatorToUse == null) {
        // 2.如果沒有設置比較器, 則使用默認的OrderComparator
        comparatorToUse = OrderComparator.INSTANCE;
    }
    // 3.使用比較器對postProcessors進行排序
    Collections.sort(postProcessors, comparatorToUse);
}

默認情況下,比較器爲 OrderComparator;如果配置了 annotation-config,並且值爲true,使用的是 AnnotationAwareOrderComparator( Spring IoC:context:component-scan節點解析 代碼塊17中設置了dependencyComparator 屬性爲 AnnotationAwareOrderComparator.INSTANCE),AnnotationAwareOrderComparator 繼承自 OrderComparator,只是重寫了部分方法,比較器的部分代碼如下:

@Override
public int compare(Object o1, Object o2) {
    return doCompare(o1, o2, null);
}

private int doCompare(Object o1, Object o2, OrderSourceProvider sourceProvider) {
    // 判斷o1是否實現了PriorityOrdered接口
    boolean p1 = (o1 instanceof PriorityOrdered);
    // 判斷o2是否實現了PriorityOrdered接口
    boolean p2 = (o2 instanceof PriorityOrdered);
    // 1.如果o1實現了PriorityOrdered接口, 而o2沒有, 則o1排前面
    if (p1 && !p2) {
        return -1;
    }
    // 2.如果o2實現了PriorityOrdered接口, 而o1沒有, 則o2排前面
    else if (p2 && !p1) {
        return 1;
    }

    // 3.如果o1和o2都實現(都沒實現)PriorityOrdered接口
    // Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation.
    // 拿到o1的order值, 如果沒實現Ordered接口, 值爲Ordered.LOWEST_PRECEDENCE
    int i1 = getOrder(o1, sourceProvider);
    // 拿到o2的order值, 如果沒實現Ordered接口, 值爲Ordered.LOWEST_PRECEDENCE
    int i2 = getOrder(o2, sourceProvider);
    // 4.通過order值(order值越小, 優先級越高)排序
    return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}

比較器的邏輯很簡單,實現 PriorityOrdered 接口的優先級最高,如果兩個對象都實現(都沒實現)PriorityOrdered 接口,則根據 order 值(實現 Ordered 接口時,需要實現 getOrder() 方法,返回 order 值)來進行比較,order 值越小,優先級越高。

 

基本使用

1.BeanDefinitionRegistryPostProcessor 的擴展使用

使用方法比較簡單,新建一個類實現 BeanDefinitionRegistryPostProcessor 接口,並將該類註冊到 Spring IoC 容器中。

package com.joonwhee.open.demo.spring;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

/**
 * @author joonwhee
 * @date 2019/2/18
 */
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, Ordered {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry");
        // 自己的邏輯處理
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor#postProcessBeanFactory");
        // 自己的邏輯處理
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

具體的使用場景,需要讀者自己去探討,這邊給一個常見的使用例子。

例子:

我們通常在使用 Mybatis + Spring 時,經常用到的 org.mybatis.spring.mapper.MapperScannerConfigurer 就是一個BeanDefinitionRegistryPostProcessor。MapperScannerConfigurer 在 postProcessBeanDefinitionRegistry 方法中進行了一些操作,主要是:掃描 basePackage 指定的目錄,將該目錄下的類(通常是 DAO/MAPPER 接口)封裝成 BeanDefinition 並加載到 BeanFactory 中。因此,我們可以看到我們項目中的 DAO(MAPPER)接口,通常都沒有使用註解或 XML 的方式註冊到 Spring 容器,但是我們還是可以在 Service 服務中,使用 @Autowire 註解來將其注入到 Service 中,就是因爲這個原因。

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!--basePackage指定要掃描的包,在此包之下的映射器都會被搜索到。可指定多個包,包與包之間用逗號或分號分隔-->
    <property name="basePackage" value="com.joonwhee.open.demo.mapper"/>
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

MapperScannerConfigurer.java

 

2.BeanFactoryPostProcessor 的擴展使用

使用方法跟 BeanDefinitionRegistryPostProcessor 類似。

package com.joonwhee.open.demo.spring;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;

/**
 * @author joonwhee
 * @date 2019/2/18
 */
@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanFactoryPostProcessor#postProcessBeanFactory");
        // 自己的邏輯處理
    }
}

 

總結

invokeBeanFactoryPostProcessors 方法的內容其實比較少,大部分過程在代碼塊2的註釋都已經寫清楚,這邊在稍微總結一下。

1.整個 invokeBeanFactoryPostProcessors 方法圍繞兩個接口,BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor,其中 BeanDefinitionRegistryPostProcessor 繼承了 BeanFactoryPostProcessor 。BeanDefinitionRegistryPostProcessor 主要用來在常規 BeanFactoryPostProcessor 檢測開始之前註冊其他 Bean 定義,說的簡單點,就是 BeanDefinitionRegistryPostProcessor 具有更高的優先級,執行順序在 BeanFactoryPostProcessor 之前。

2.整個 invokeBeanFactoryPostProcessors 方法操作了 3 種 bean 對象:

  • 入參 beanFactoryPostProcessors:這個我們在代碼塊1中解析過,拿的是 AbstractApplicationContext 類的 beanFactoryPostProcessors 屬性值,也就是在之前已經添加到 beanFactoryPostProcessors 中的 BeanFactoryPostProcessor。
  • BeanDefinitionRegistryPostProcessor 接口實現類:實現了 BeanDefinitionRegistryPostProcessor 接口,並且註冊到 Spring IoC容器中。
  • 常規 BeanFactoryPostProcessor 接口實現類:實現了 BeanFactoryPostProcessor 接口,並且註冊到 Spring IoC容器中。

3.操作3種 bean 對象具體指的是調用它們重寫的方法,調用實現方法時會遵循以下的優先級:

  • 第一優先級:入參 beanFactoryPostProcessors 中的 BeanDefinitionRegistryPostProcessor, 調用 postProcessBeanDefinitionRegistry 方法(2.1.1)。
  • 第二優先級:BeanDefinitionRegistryPostProcessor 接口實現類,並且實現了 PriorityOrdered 接口,調用 postProcessBeanDefinitionRegistry 方法(3.8)。
  • 第三優先級:BeanDefinitionRegistryPostProcessor 接口實現類,並且實現了 Ordered 接口,調用 postProcessBeanDefinitionRegistry 方法(4.2)。
  • 第四優先級:除去第二優先級和第三優先級,剩餘的 BeanDefinitionRegistryPostProcessor 接口實現類,調用 postProcessBeanDefinitionRegistry 方法(5.4)。
  • 第五優先級:所有 BeanDefinitionRegistryPostProcessor 接口實現類,調用 postProcessBeanFactory 方法(6)。
  • 第六優先級:入參 beanFactoryPostProcessors 中的常規 BeanFactoryPostProcessor,調用 postProcessBeanFactory 方法(7)。
  • 第七優先級:常規 BeanFactoryPostProcessor 接口實現類,並且實現了 PriorityOrdered 接口,調用 postProcessBeanFactory 方法(9.2)。
  • 第八優先級:常規 BeanFactoryPostProcessor 接口實現類,並且實現了 Ordered 接口,調用 postProcessBeanFactory 方法(10.3)。
  • 第九優先級:除去第七優先級和第八優先級,剩餘的常規 BeanFactoryPostProcessor 接口的實現類,調用 postProcessBeanFactory 方法(11.2)。

4.本文還引入了兩個用於排序的重要接口:PriorityOrdered 和 Ordered,其中 PriorityOrdered 繼承了 Ordered,並且 PriorityOrdered 的優先級要高於 Ordered,這跟 BeanDefinitionRegistryPostProcessor 繼承 BeanFactoryPostProcessor 有點類似。實現 Ordered 接口需要重寫 getOrder 方法,返回一個用於排序的 order 值,order 值的範圍爲 Integer.MIN_VALUE ~ Integer.MAX_VALUE,order 值越小優先級越高,Integer.MIN_VALUE 擁有最高優先級,而 Integer.MAX_VALUE 則對應的擁有最低優先級。

5.常見的 Java EE 相關的框架或者中間件,經常使用 BeanFactoryPostProcessor 來進行擴展,例如上面的 Mybatis,因此瞭解 BeanFactoryPostProcessor 的原理會對之後理解其他中間件的原理有幫助。

 

另外,我還準備了很多大廠面試資料、0基礎自學教程,由於不能放外鏈,所以有需要的小夥伴去公衆號【程序員囧輝】回覆【資料】自行獲取好了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章