SmartInstantiationAwareBeanPostProcessor源碼分析

SmartInstantiationAwareBeanPostProcessor

一、基本信息

?? 作者 - Lex ?? 博客 - 我的CSDN ?? 文章目錄 - 所有文章 ?? 源碼地址 - SmartInstantiationAwareBeanPostProcessor源碼

二、接口描述

InstantiationAwareBeanPostProcessor。接口,能夠?qū)?Spring 容器創(chuàng)建的 beans 進(jìn)行更精細(xì)的控制和更多的干預(yù),尤其是在涉及代理和其他高級(jí)場(chǎng)景時(shí)。

三、接口源碼

SmartInstantiationAwareBeanPostProcessor 是 Spring 框架自 2.0.3 版本開始引入的一個(gè)核心接口,主要用于框架內(nèi)部。正常情況下我們實(shí)現(xiàn)BeanPostProcessor接口或者InstantiationAwareBeanPostProcessorAdapter接口就能滿足自定義需求。

/**
 * InstantiationAwareBeanPostProcessor 接口的擴(kuò)展,
 * 增加了預(yù)測(cè)處理的bean的最終類型的回調(diào)方法。
 *
 * 注意: 這是一個(gè)特定目的的接口,主要用于
 * 框架內(nèi)部。一般來(lái)說(shuō),應(yīng)用程序提供的后處理器應(yīng)該
 * 直接實(shí)現(xiàn)簡(jiǎn)單的 BeanPostProcessor
 * 接口或繼承 InstantiationAwareBeanPostProcessorAdapter 類。
 * 即使在點(diǎn)版本中,也可能向此接口添加新方法。
 *
 * @author Juergen Hoeller
 * @since 2.0.3
 * @see InstantiationAwareBeanPostProcessorAdapter
 */
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {

    /**
     * 預(yù)測(cè)從此處理器的 #postProcessBeforeInstantiation 回調(diào)返回的bean的類型。
     * 默認(rèn)實(shí)現(xiàn)返回 null。
     * @param beanClass bean的原始類
     * @param beanName bean的名稱
     * @return bean的類型,如果不可預(yù)測(cè)則為 null
     * @throws org.springframework.beans.BeansException 出錯(cuò)時(shí)拋出
     */
    @Nullable
    default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
        return null;
    }

    /**
     * 確定給定bean的候選構(gòu)造函數(shù)。
     * 默認(rèn)實(shí)現(xiàn)返回 null。
     * @param beanClass bean的原始類(永遠(yuǎn)不是 null)
     * @param beanName bean的名稱
     * @return 候選構(gòu)造函數(shù),如果沒(méi)有指定則為 null
     * @throws org.springframework.beans.BeansException 出錯(cuò)時(shí)拋出
     */
    @Nullable
    default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
            throws BeansException {

        return null;
    }

    /**
     * 為了解決循環(huán)引用,提前獲取指定bean的引用。
     * 此回調(diào)為后處理器提供了一個(gè)機(jī)會(huì),可以在目標(biāo)bean實(shí)例完全初始化之前暴露一個(gè)包裝器。
     * 暴露的對(duì)象應(yīng)當(dāng)?shù)韧?#postProcessBeforeInitialization / 
     * #postProcessAfterInitialization 否則會(huì)暴露。需要注意的是,
     * 由此方法返回的對(duì)象將被用作bean引用,除非后處理器從上述后處理回調(diào)中返回一個(gè)不同的包裝器。
     * 默認(rèn)實(shí)現(xiàn)返回給定的 bean 原樣。
     * @param bean 原始bean實(shí)例
     * @param beanName bean的名稱
     * @return 作為bean引用暴露的對(duì)象(通常使用傳入的bean實(shí)例作為默認(rèn)值)
     * @throws org.springframework.beans.BeansException 出錯(cuò)時(shí)拋出
     */
    default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

四、主要功能

  1. 預(yù)測(cè) Bean 類型 (predictBeanType)

    • 這個(gè)方法允許在實(shí)例化 bean 之前預(yù)測(cè) bean 的最終類型。這在涉及代理或其他類型轉(zhuǎn)換的場(chǎng)景中特別有用,例如,一個(gè) bean 可能會(huì)被一個(gè) AOP 代理包裹,此方法可以返回預(yù)期的代理類型而不是實(shí)際的目標(biāo)類型,這有助于 Spring 在創(chuàng)建和連接 bean 時(shí)做出更加明智的決策,特別是在涉及類型匹配(如自動(dòng)裝配)時(shí)。
  2. 確定候選構(gòu)造函數(shù) (determineCandidateConstructors)

    • 在 bean 實(shí)例化之前,這個(gè)方法允許確定用于給定 bean 的構(gòu)造函數(shù),這為我們提供了一種方式來(lái)定制或干預(yù) Spring 默認(rèn)的構(gòu)造函數(shù)選擇邏輯,例如,當(dāng)存在多個(gè)構(gòu)造函數(shù)并且我們想基于特定邏輯選擇其中一個(gè)時(shí)。
  3. 獲取早期 Bean 引用 (getEarlyBeanReference)

    • 這個(gè)方法提供了一個(gè)機(jī)會(huì),允許在 bean 完全初始化之前暴露一個(gè)包裝器或代理,它在處理循環(huán)依賴時(shí)特別有用,當(dāng)一個(gè) bean 還未完全初始化但另一個(gè) bean 需要引用它時(shí),這個(gè)方法就會(huì)被調(diào)用,這樣,我們可以暴露一個(gè)早期的 bean 引用,可能是一個(gè)代理,這個(gè)代理在完成所有初始化步驟后仍然有效。

五、最佳實(shí)踐

首先來(lái)看看啟動(dòng)類入口,上下文環(huán)境使用AnnotationConfigApplicationContext(此類是使用Java注解來(lái)配置Spring容器的方式),構(gòu)造參數(shù)我們給定了一個(gè)MyConfiguration組件類。

public class SmartInstantiationAwareBeanPostProcessorApplication {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
    }
}

這里使用@Bean注解,定義了一個(gè)Bean,是為了確保 MySmartInstantiationAwareBeanPostProcessor 被 Spring 容器執(zhí)行

@Configuration
@ComponentScan("com.xcs.spring")
public class MyConfiguration {

    @Bean
    public static MySmartInstantiationAwareBeanPostProcessor mySmartInstantiationAwareBeanPostProcessor(){
        return new MySmartInstantiationAwareBeanPostProcessor();
    }
}

自定義的 SmartInstantiationAwareBeanPostProcessor 實(shí)現(xiàn),然后我們重寫了 determineCandidateConstructors 方法。如果類中有一個(gè)或多個(gè)帶有 @MyAutowired 注解的構(gòu)造函數(shù),這些構(gòu)造函數(shù)將被作為候選返回,如果沒(méi)有找到任何帶有 @MyAutowired 注解的構(gòu)造函數(shù),那么后處理器會(huì)嘗試查找默認(rèn)(無(wú)參數(shù))的構(gòu)造函數(shù),如果沒(méi)有找到帶有 @MyAutowired 注解的構(gòu)造函數(shù),并且沒(méi)有默認(rèn)構(gòu)造函數(shù),那么所有可用的構(gòu)造函數(shù)將被作為候選返回,從而使 Spring 能夠選擇最具體的構(gòu)造函數(shù)。

public class MySmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {

    @Override
    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
        // 首先,查找@MyAutowired帶注釋的構(gòu)造函數(shù)
        List<Constructor<?>> myAutowiredConstructors = Arrays.stream(beanClass.getConstructors())
                .filter(constructor -> constructor.isAnnotationPresent(MyAutowired.class))
                .collect(Collectors.toList());

        if (!myAutowiredConstructors.isEmpty()) {
            return myAutowiredConstructors.toArray(new Constructor<?>[0]);
        }

        // 其次,檢查默認(rèn)構(gòu)造函數(shù)
        try {
            Constructor<?> defaultConstructor = beanClass.getDeclaredConstructor();
            return new Constructor<?>[]{defaultConstructor};
        } catch (NoSuchMethodException e) {
            // 找不到默認(rèn)構(gòu)造函數(shù),請(qǐng)繼續(xù)選擇合適的構(gòu)造函數(shù)
        }

        // 返回所有構(gòu)造函數(shù),讓Spring將選擇最具體的構(gòu)造函數(shù)
        return beanClass.getConstructors();
    }
}

自定義注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.CONSTRUCTOR)
public @interface MyAutowired {
    
}

兩個(gè)普通Bean對(duì)象

@Component
public class MyServiceA {

    public void execute() {
        System.out.println("MyServiceA executed");
    }
}

@Component
public class MyServiceB {

    public void execute() {
        System.out.println("MyServiceB executed");
    }
}

我們定義了四個(gè)構(gòu)造函數(shù)(默認(rèn)構(gòu)造函數(shù),只接受 MyServiceA 的構(gòu)造函數(shù),只接受 MyServiceB 的構(gòu)造函數(shù),同時(shí)接受 MyServiceAMyServiceB 的構(gòu)造函數(shù))。根據(jù)MySmartInstantiationAwareBeanPostProcessor定義的分析下面選擇構(gòu)造函數(shù)過(guò)程,當(dāng) Spring 容器嘗試實(shí)例化 MyService 類的一個(gè)實(shí)例時(shí),由于存在一個(gè)被 @MyAutowired 標(biāo)記的構(gòu)造函數(shù),所以它將首先嘗試使用它。這意味著如果在 Spring 容器中已經(jīng)有了 MyServiceAMyServiceB 的 bean,那么這兩者都會(huì)被注入,并且會(huì)輸出 "Constructor with ServiceA and ServiceB used"。如果沒(méi)有提供 @MyAutowired 或者沒(méi)有適當(dāng)?shù)?bean 來(lái)滿足帶有 @MyAutowired 注解的構(gòu)造函數(shù)的依賴關(guān)系,則會(huì)嘗試使用默認(rèn)構(gòu)造函數(shù)。如果沒(méi)有默認(rèn)構(gòu)造函數(shù),Spring 將嘗試其他構(gòu)造函數(shù)并查找可以匹配的 bean。在這種情況下,如果 MyServiceAMyServiceB 都可用,Spring 將選擇接受最多參數(shù)的構(gòu)造函數(shù),因?yàn)檫@被視為最具體的構(gòu)造函數(shù)。

@Component
public class MyService {

    private final MyServiceA myServiceA;
    private final MyServiceB myServiceB;

    public MyService() {
        System.out.println("Default constructor used");
        this.myServiceA = null;
        this.myServiceB = null;
    }

    public MyService(MyServiceA myServiceA) {
        System.out.println("Constructor with ServiceA used");
        this.myServiceA = myServiceA;
        this.myServiceB = null;
    }

    public MyService(MyServiceB serviceB) {
        System.out.println("Constructor with ServiceB used");
        this.myServiceA = null;
        this.myServiceB = serviceB;
    }

    @MyAutowired
    public MyService(MyServiceA serviceA, MyServiceB serviceB) {
        System.out.println("Constructor with ServiceA and ServiceB used");
        this.myServiceA = serviceA;
        this.myServiceB = serviceB;
    }
}

運(yùn)行結(jié)果發(fā)現(xiàn),Spring 容器成功地使用帶有 @MyAutowired 注解的構(gòu)造函數(shù)實(shí)例化了 MyService 類,并正確地注入了它的兩個(gè)依賴:MyServiceAMyServiceB。

Constructor with ServiceA and ServiceB used

<span style="color:red">注意:由于predictBeanType,getEarlyBeanReference方法是Spring框架內(nèi)部使用無(wú)法演示出效果,因此不演示這兩個(gè)方法。</span>

六、時(shí)序圖

sequenceDiagram
    Title: SmartInstantiationAwareBeanPostProcessor時(shí)序圖
    participant SmartInstantiationAwareBeanPostProcessorApplication
    participant AnnotationConfigApplicationContext
    participant AbstractApplicationContext
    participant DefaultListableBeanFactory
    participant AbstractBeanFactory
    participant DefaultSingletonBeanRegistry
    participant AbstractAutowireCapableBeanFactory
    participant MySmartInstantiationAwareBeanPostProcessor
    
    SmartInstantiationAwareBeanPostProcessorApplication->>AnnotationConfigApplicationContext:AnnotationConfigApplicationContext(componentClasses)<br>創(chuàng)建上下文
    AnnotationConfigApplicationContext->>AbstractApplicationContext:refresh()<br>刷新上下文
    AbstractApplicationContext->>AbstractApplicationContext:finishBeanFactoryInitialization(beanFactory)<br>初始化Bean工廠
    AbstractApplicationContext->>DefaultListableBeanFactory:preInstantiateSingletons()<br>實(shí)例化單例
    DefaultListableBeanFactory->>AbstractBeanFactory:getBean(name)<br>獲取Bean
    AbstractBeanFactory->>AbstractBeanFactory:doGetBean(name,requiredType,args,typeCheckOnly)<br>執(zhí)行獲取Bean
    AbstractBeanFactory->>DefaultSingletonBeanRegistry:getSingleton(beanName,singletonFactory)<br>獲取單例Bean
    DefaultSingletonBeanRegistry-->>AbstractBeanFactory:getObject()<br>獲取Bean實(shí)例
    AbstractBeanFactory->>AbstractAutowireCapableBeanFactory:createBean(beanName,mbd,args)<br>創(chuàng)建Bean
    AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:doCreateBean(beanName,mbd,args)<br>執(zhí)行Bean創(chuàng)建
    AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:createBeanInstance(beanName,mbd,args)<br>創(chuàng)建bean實(shí)例
    AbstractAutowireCapableBeanFactory->>AbstractAutowireCapableBeanFactory:determineConstructorsFromBeanPostProcessors(beanClass, beanName)<br>確定構(gòu)造方法
    AbstractAutowireCapableBeanFactory->>MySmartInstantiationAwareBeanPostProcessor:determineCandidateConstructors(beanClass, beanName)<br>回調(diào)候選構(gòu)造方法
    MySmartInstantiationAwareBeanPostProcessor-->>AbstractAutowireCapableBeanFactory:返回構(gòu)造方法
    AbstractAutowireCapableBeanFactory-->>AbstractBeanFactory:返回Bean對(duì)象
    AbstractBeanFactory-->>DefaultListableBeanFactory:返回Bean對(duì)象
    AnnotationConfigApplicationContext-->>SmartInstantiationAwareBeanPostProcessorApplication:初始化完成

七、源碼分析

首先來(lái)看看啟動(dòng)類入口,上下文環(huán)境使用AnnotationConfigApplicationContext(此類是使用Java注解來(lái)配置Spring容器的方式),構(gòu)造參數(shù)我們給定了一個(gè)MyConfiguration組件類。

<span style="color:red">PS:由于predictBeanType, determineCandidateConstructors, 和 getEarlyBeanReference 這三個(gè)方法雖然都屬于 SmartInstantiationAwareBeanPostProcessor 接口,但它們處理不同的關(guān)注點(diǎn),具有不同的目的。在進(jìn)行源碼分析時(shí),此處只演示determineCandidateConstructors方法。</span>

public class SmartInstantiationAwareBeanPostProcessorApplication {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
    }
}

org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext構(gòu)造函數(shù)中,執(zhí)行了三個(gè)步驟,我們重點(diǎn)關(guān)注refresh()方法

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();
    register(componentClasses);
    refresh();
}

org.springframework.context.support.AbstractApplicationContext#refresh方法中,我們重點(diǎn)關(guān)注一下finishBeanFactoryInitialization(beanFactory)這方法會(huì)對(duì)實(shí)例化所有剩余非懶加載的單列Bean對(duì)象,其他方法不是本次源碼閱讀的重點(diǎn)暫時(shí)忽略。

@Override
public void refresh() throws BeansException, IllegalStateException {
    // ... [代碼部分省略以簡(jiǎn)化]
    // Instantiate all remaining (non-lazy-init) singletons.
    finishBeanFactoryInitialization(beanFactory);
    // ... [代碼部分省略以簡(jiǎn)化]
}

org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization方法中,會(huì)繼續(xù)調(diào)用DefaultListableBeanFactory類中的preInstantiateSingletons方法來(lái)完成所有剩余非懶加載的單列Bean對(duì)象。

/**
 * 完成此工廠的bean初始化,實(shí)例化所有剩余的非延遲初始化單例bean。
 * 
 * @param beanFactory 要初始化的bean工廠
 */
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // ... [代碼部分省略以簡(jiǎn)化]
    // 完成所有剩余非懶加載的單列Bean對(duì)象。
    beanFactory.preInstantiateSingletons();
}

org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons方法中,主要的核心目的是預(yù)先實(shí)例化所有非懶加載的單例bean。在Spring的上下文初始化完成后,該方法會(huì)被觸發(fā),以確保所有單例bean都被正確地創(chuàng)建并初始化。其中getBean(beanName)是此方法的核心操作。對(duì)于容器中定義的每一個(gè)單例bean,它都會(huì)調(diào)用getBean方法,這將觸發(fā)bean的實(shí)例化、初始化及其依賴的注入。如果bean之前沒(méi)有被創(chuàng)建過(guò),那么這個(gè)調(diào)用會(huì)導(dǎo)致其被實(shí)例化和初始化。

public void preInstantiateSingletons() throws BeansException {
    // ... [代碼部分省略以簡(jiǎn)化]
    // 循環(huán)遍歷所有bean的名稱
    for (String beanName : beanNames) {
        getBean(beanName);
    }
    // ... [代碼部分省略以簡(jiǎn)化]
}

org.springframework.beans.factory.support.AbstractBeanFactory#getBean()方法中,又調(diào)用了doGetBean方法來(lái)實(shí)際執(zhí)行創(chuàng)建Bean的過(guò)程,傳遞給它bean的名稱和一些其他默認(rèn)的參數(shù)值。此處,doGetBean負(fù)責(zé)大部分工作,如查找bean定義、創(chuàng)建bean(如果尚未創(chuàng)建)、處理依賴關(guān)系等。

@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean方法中,首先檢查所請(qǐng)求的bean是否是一個(gè)單例并且已經(jīng)創(chuàng)建。如果尚未創(chuàng)建,它將創(chuàng)建一個(gè)新的實(shí)例。在這個(gè)過(guò)程中,它處理可能的異常情況,如循環(huán)引用,并確保返回的bean是正確的類型。這是Spring容器bean生命周期管理的核心部分。

protected <T> T doGetBean(
        String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
        throws BeansException {
    // ... [代碼部分省略以簡(jiǎn)化]

    // 開始創(chuàng)建bean實(shí)例
    if (mbd.isSingleton()) {
        // 如果bean是單例的,我們會(huì)嘗試從單例緩存中獲取它
        // 如果不存在,則使用lambda創(chuàng)建一個(gè)新的實(shí)例
        sharedInstance = getSingleton(beanName, () -> {
            try {
                // 嘗試創(chuàng)建bean實(shí)例
                return createBean(beanName, mbd, args);
            }
            catch (BeansException ex) {
                // ... [代碼部分省略以簡(jiǎn)化]
            }
        });
        // 對(duì)于某些bean(例如FactoryBeans),可能需要進(jìn)一步處理以獲取真正的bean實(shí)例
        beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    // ... [代碼部分省略以簡(jiǎn)化]

    // 確保返回的bean實(shí)例與請(qǐng)求的類型匹配
    return adaptBeanInstance(name, beanInstance, requiredType);
}

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton()方法中,主要負(fù)責(zé)從單例緩存中獲取一個(gè)已存在的bean實(shí)例,或者使用提供的ObjectFactory創(chuàng)建一個(gè)新的實(shí)例。這是確保bean在Spring容器中作為單例存在的關(guān)鍵部分。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    // 斷言bean名稱不能為空
    Assert.notNull(beanName, "Bean name must not be null");

    // 同步訪問(wèn)單例對(duì)象緩存,確保線程安全
    synchronized (this.singletonObjects) {
        // 從緩存中獲取單例對(duì)象
        Object singletonObject = this.singletonObjects.get(beanName);

        // 如果緩存中沒(méi)有找到
        if (singletonObject == null) {
            // ... [代碼部分省略以簡(jiǎn)化]

            try {
                // 使用工廠創(chuàng)建新的單例實(shí)例
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (IllegalStateException ex) {
                // ... [代碼部分省略以簡(jiǎn)化]
            }
            catch (BeanCreationException ex) {
                // ... [代碼部分省略以簡(jiǎn)化]
            }
            finally {
                // ... [代碼部分省略以簡(jiǎn)化]
            }

            // ... [代碼部分省略以簡(jiǎn)化]
        }

        // 返回單例對(duì)象
        return singletonObject;
    }
}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean()方法中,主要的邏輯是調(diào)用 doCreateBean,這是真正進(jìn)行 bean 實(shí)例化、屬性填充和初始化的地方。這個(gè)方法會(huì)返回新創(chuàng)建的 bean 實(shí)例。

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    throws BeanCreationException {
    
    // ... [代碼部分省略以簡(jiǎn)化]
    
    try {
        // 正常的bean實(shí)例化、屬性注入和初始化。
        // 這里是真正進(jìn)行bean創(chuàng)建的部分。
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        // 記錄bean成功創(chuàng)建的日志
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        // ... [代碼部分省略以簡(jiǎn)化]
    }
    catch (Throwable ex) {
        // ... [代碼部分省略以簡(jiǎn)化]
    }
}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean方法中,如果是單例,嘗試從工廠實(shí)例緩存中獲取。如果緩存中沒(méi)有實(shí)例,創(chuàng)建一個(gè)新的實(shí)例。

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {
    // 實(shí)例化 bean。
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        // 如果是單例,嘗試從工廠實(shí)例緩存中獲取。
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // 如果緩存中沒(méi)有實(shí)例,創(chuàng)建一個(gè)新的實(shí)例。
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    
    // ... [省略部分代碼以簡(jiǎn)化]

    // 返回創(chuàng)建和初始化后的 bean。
    return exposedObject;
}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance方法中,首先嘗試從 SmartInstantiationAwareBeanPostProcessor 中確定用于 bean 的構(gòu)造函數(shù),接下來(lái),它檢查是否已經(jīng)確定了某些構(gòu)造函數(shù)、是否 bean 定義指明了使用構(gòu)造函數(shù)自動(dòng)裝配、是否為 bean 提供了構(gòu)造函數(shù)參數(shù)值或是否有明確的構(gòu)造函數(shù)參數(shù)。如果滿足這些條件之一,它將調(diào)用 autowireConstructor 方法,這個(gè)方法會(huì)使用確定的構(gòu)造函數(shù)(或者選擇一個(gè))來(lái)實(shí)例化 bean。接著,如果之前沒(méi)有選擇構(gòu)造函數(shù),它會(huì)檢查是否存在首選的默認(rèn)構(gòu)造函數(shù)。這些構(gòu)造函數(shù)可以是由用戶明確指定的或是由其他部分的框架預(yù)先確定的。如果有這樣的構(gòu)造函數(shù),框架又會(huì)嘗試使用 autowireConstructor 方法,最后,如果所有先前的步驟都沒(méi)有返回構(gòu)造函數(shù),spring會(huì)默認(rèn)為 bean 使用無(wú)參數(shù)構(gòu)造函數(shù)。

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // ... [省略部分代碼以簡(jiǎn)化]

    // 是否有用于自動(dòng)裝配的候選構(gòu)造函數(shù)?
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    // 如果從后處理器中確定了構(gòu)造函數(shù)、或者 bean 定義信息指明了使用構(gòu)造函數(shù)自動(dòng)裝配、或者存在構(gòu)造函數(shù)參數(shù)值、或者提供了特定的構(gòu)造函數(shù)參數(shù)
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
        mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        // 使用確定的構(gòu)造函數(shù)進(jìn)行自動(dòng)裝配
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // 是否有優(yōu)先使用的默認(rèn)構(gòu)造函數(shù)?
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
        // 使用優(yōu)選的構(gòu)造函數(shù)進(jìn)行自動(dòng)裝配
        return autowireConstructor(beanName, mbd, ctors, null);
    }

    // 沒(méi)有特殊處理:直接使用無(wú)參數(shù)構(gòu)造函數(shù)進(jìn)行實(shí)例化
    return instantiateBean(beanName, mbd);
}

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#determineConstructorsFromBeanPostProcessors方法中,回調(diào)每一個(gè) SmartInstantiationAwareBeanPostProcessor,調(diào)用它的 determineCandidateConstructors 方法以確定 bean 的構(gòu)造函數(shù)。如果找到了候選的構(gòu)造函數(shù),就返回這些構(gòu)造函數(shù)。如果多個(gè) SmartInstantiationAwareBeanPostProcessor 都返回了構(gòu)造函數(shù),則只會(huì)使用第一個(gè)返回的構(gòu)造函數(shù)。

protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
            throws BeansException {

    if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
        for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
            Constructor<?>[] ctors = bp.determineCandidateConstructors(beanClass, beanName);
            if (ctors != null) {
                return ctors;
            }
        }
    }
    return null;
}

最后執(zhí)行到我們自定義的邏輯中,在我們自定義的邏輯中,如果類中有一個(gè)或多個(gè)帶有 @MyAutowired 注解的構(gòu)造函數(shù),這些構(gòu)造函數(shù)將被作為候選返回,如果沒(méi)有找到任何帶有 @MyAutowired 注解的構(gòu)造函數(shù),那么后處理器會(huì)嘗試查找默認(rèn)(無(wú)參數(shù))的構(gòu)造函數(shù),如果沒(méi)有找到帶有 @MyAutowired 注解的構(gòu)造函數(shù),并且沒(méi)有默認(rèn)構(gòu)造函數(shù),那么所有可用的構(gòu)造函數(shù)將被作為候選返回,從而使 Spring 能夠選擇最具體的構(gòu)造函數(shù)。

public class MySmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {

    @Override
    public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
        // 首先,查找@MyAutowired帶注釋的構(gòu)造函數(shù)
        List<Constructor<?>> myAutowiredConstructors = Arrays.stream(beanClass.getConstructors())
                .filter(constructor -> constructor.isAnnotationPresent(MyAutowired.class))
                .collect(Collectors.toList());

        if (!myAutowiredConstructors.isEmpty()) {
            return myAutowiredConstructors.toArray(new Constructor<?>[0]);
        }

        // 其次,檢查默認(rèn)構(gòu)造函數(shù)
        try {
            Constructor<?> defaultConstructor = beanClass.getDeclaredConstructor();
            return new Constructor<?>[]{defaultConstructor};
        } catch (NoSuchMethodException e) {
            // 找不到默認(rèn)構(gòu)造函數(shù),請(qǐng)繼續(xù)選擇合適的構(gòu)造函數(shù)
        }

        // 返回所有構(gòu)造函數(shù),讓Spring將選擇最具體的構(gòu)造函數(shù)
        return beanClass.getConstructors();
    }
}

八、注意事項(xiàng)

  1. 性能影響

    • 每個(gè) SmartInstantiationAwareBeanPostProcessor,都會(huì)對(duì)每個(gè) bean 的創(chuàng)建過(guò)程產(chǎn)生額外的開銷。因此,應(yīng)避免創(chuàng)建不必要的 SmartInstantiationAwareBeanPostProcessor,并確保其實(shí)現(xiàn)盡可能高效。
  2. 與其他后處理器的交互

    • 如果有多個(gè) SmartInstantiationAwareBeanPostProcessor ,它們會(huì)按照注冊(cè)的順序被調(diào)用。應(yīng)確保這些后處理器的執(zhí)行順序是正確的,避免意外的覆蓋或沖突,因?yàn)橹粫?huì)使用第一個(gè)返回的構(gòu)造函數(shù)。
  3. 返回非空值的考慮

    • determineCandidateConstructors:當(dāng)這個(gè)方法返回非空值時(shí),Spring 容器將不會(huì)再嘗試使用其他方式自動(dòng)選擇構(gòu)造函數(shù),predictBeanType:返回的類型應(yīng)該盡可能準(zhǔn)確地反映后處理器預(yù)期的最終 bean 類型,以確保類型匹配和自動(dòng)裝配的正確性。
  4. InstantiationAwareBeanPostProcessor 的區(qū)別

    • 雖然 SmartInstantiationAwareBeanPostProcessor 擴(kuò)展了 InstantiationAwareBeanPostProcessor,但它添加了更多的回調(diào)和復(fù)雜性。除非我們確實(shí)需要這些額外的功能,否則最好僅使用 InstantiationAwareBeanPostProcessor。

九、總結(jié)

最佳實(shí)踐總結(jié)

  1. 初始化 Spring 容器

    • 通過(guò) AnnotationConfigApplicationContext 初始化 Spring 容器,并使用 MyConfiguration 作為配置類。
  2. 注冊(cè)后處理器

    • MyConfiguration 中,我們注冊(cè)了自定義的 SmartInstantiationAwareBeanPostProcessor 實(shí)現(xiàn) MySmartInstantiationAwareBeanPostProcessor。這確保了它會(huì)在 Spring 容器中被考慮并執(zhí)行。
  3. 自定義后處理器的工作

    • 我們的 MySmartInstantiationAwareBeanPostProcessor 重寫了 determineCandidateConstructors 方法,該方法的目標(biāo)是返回一組構(gòu)造函數(shù),供 Spring 選擇用于 bean 的實(shí)例化。
  4. 查找 @MyAutowired

    • 首先,后處理器會(huì)查找?guī)в?@MyAutowired 注解的構(gòu)造函數(shù)。
  5. 使用默認(rèn)構(gòu)造函數(shù)

    • 如果沒(méi)有帶有 @MyAutowired 的構(gòu)造函數(shù),后處理器會(huì)查找默認(rèn)構(gòu)造函數(shù)。
  6. 返回所有構(gòu)造函數(shù)

    • 如果沒(méi)有找到上述兩種情況的構(gòu)造函數(shù),所有的構(gòu)造函數(shù)將被作為候選返回。
  7. Bean 的實(shí)例化

    • 當(dāng) Spring 嘗試實(shí)例化 MyService bean 時(shí),它會(huì)使用 MySmartInstantiationAwareBeanPostProcessor 中指定的構(gòu)造函數(shù)。在這個(gè)示例中,由于我們有一個(gè)帶有 @MyAutowired 注解的構(gòu)造函數(shù),且兩個(gè)依賴 MyServiceAMyServiceB 都可用,這個(gè)構(gòu)造函數(shù)被選擇并使用,從而輸出了 "Constructor with ServiceA and ServiceB used"。
  8. 關(guān)于其他方法

    • 雖然 SmartInstantiationAwareBeanPostProcessor 提供了其他方法,如 predictBeanTypegetEarlyBeanReference,但這些主要是為 Spring 內(nèi)部使用。在大多數(shù)常規(guī)用例中,我們可能不需要重寫或使用它們。

源碼分析總結(jié)

  1. 啟動(dòng)和初始化:

    • 使用AnnotationConfigApplicationContext初始化Spring上下文。

    • 構(gòu)造參數(shù)中給定一個(gè)配置類,該配置類中定義了自定義的SmartInstantiationAwareBeanPostProcessor

  1. Bean預(yù)實(shí)例化過(guò)程:

    • 在上下文刷新過(guò)程中,finishBeanFactoryInitialization方法會(huì)預(yù)實(shí)例化所有非懶加載的單例Bean。

    • preInstantiateSingletons方法循環(huán)遍歷所有bean的名稱并通過(guò)getBean方法實(shí)例化bean。

    • 如果Bean已經(jīng)存在并且是單例,則會(huì)從單例緩存中返回。否則,會(huì)創(chuàng)建一個(gè)新的bean實(shí)例。

  1. Bean創(chuàng)建過(guò)程:

    • 創(chuàng)建Bean的核心邏輯在doCreateBean方法中。如果bean是單例并且在緩存中不存在,則會(huì)創(chuàng)建一個(gè)新的bean實(shí)例。

    • 在創(chuàng)建bean實(shí)例時(shí),首先從SmartInstantiationAwareBeanPostProcessor中確定用于bean的構(gòu)造函數(shù)。

    • 這個(gè)過(guò)程首先嘗試使用帶有特定注解(如我們的示例中的@MyAutowired)的構(gòu)造函數(shù)。

    • 如果沒(méi)有這樣的構(gòu)造函數(shù),則會(huì)選擇默認(rèn)構(gòu)造函數(shù)。

    • 如果沒(méi)有帶有注解的構(gòu)造函數(shù)且沒(méi)有默認(rèn)構(gòu)造函數(shù),則會(huì)返回所有可用的構(gòu)造函數(shù),從而使Spring選擇最具體的構(gòu)造函數(shù)。

  1. 自定義的邏輯:

    • 自定義的SmartInstantiationAwareBeanPostProcessor實(shí)現(xiàn)首先檢查是否有帶有@MyAutowired注解的構(gòu)造函數(shù)。

    • 如果有,則這些構(gòu)造函數(shù)會(huì)作為候選返回。

    • 如果沒(méi)有,則后處理器會(huì)檢查是否存在默認(rèn)的無(wú)參數(shù)構(gòu)造函數(shù)。

    • 如果既沒(méi)有帶有@MyAutowired注解的構(gòu)造函數(shù),也沒(méi)有默認(rèn)構(gòu)造函數(shù),則所有構(gòu)造函數(shù)將被作為候選返回。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容