【死磕 Spring】—– IOC 之 Factory 實例化 bean

原文出自:http://cmsblogs.com

這篇我們關注創建 bean 過程中的第一個步驟:實例化 bean,對應的方法爲: createBeanInstance(),如下:

   protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {        // 解析 bean,將 bean 類名解析爲 class 引用        Class<?> beanClass = resolveBeanClass(mbd, beanName);        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {            throw new BeanCreationException(mbd.getResourceDescription(), beanName,                    "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());        }        // 如果存在 Supplier 回調,則使用給定的回調方法初始化策略        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();        if (instanceSupplier != null) {            return obtainFromSupplier(instanceSupplier, beanName);        }        // 如果工廠方法不爲空,則使用工廠方法初始化策略        if (mbd.getFactoryMethodName() != null)  {            return instantiateUsingFactoryMethod(beanName, mbd, args);        }        boolean resolved = false;        boolean autowireNecessary = false;        if (args == null) {            // constructorArgumentLock 構造函數的常用鎖            synchronized (mbd.constructorArgumentLock) {                // 如果已緩存的解析的構造函數或者工廠方法不爲空,則可以利用構造函數解析                // 因爲需要根據參數確認到底使用哪個構造函數,該過程比較消耗性能,所有采用緩存機制                if (mbd.resolvedConstructorOrFactoryMethod != null) {                    resolved = true;                    autowireNecessary = mbd.constructorArgumentsResolved;                }            }        }        // 已經解析好了,直接注入即可        if (resolved) {            // 自動注入,調用構造函數自動注入            if (autowireNecessary) {                return autowireConstructor(beanName, mbd, null, null);            }            else {                // 使用默認構造函數構造                return instantiateBean(beanName, mbd);            }        }        // 確定解析的構造函數        // 主要是檢查已經註冊的 SmartInstantiationAwareBeanPostProcessor        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);        if (ctors != null ||                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {            // 構造函數自動注入            return autowireConstructor(beanName, mbd, ctors, args);        }        //使用默認構造函數注入        return instantiateBean(beanName, mbd);    }

實例化 bean 是一個複雜的過程,其主要的邏輯爲:

  • 如果存在 Supplier 回調,則調用 obtainFromSupplier() 進行初始化
  • 如果存在工廠方法,則使用工廠方法進行初始化
  • 首先判斷緩存,如果緩存中存在,即已經解析過了,則直接使用已經解析了的,根據 constructorArgumentsResolved 參數來判斷是使用構造函數自動注入還是默認構造函數
  • 如果緩存中沒有,則需要先確定到底使用哪個構造函數來完成解析工作,因爲一個類有多個構造函數,每個構造函數都有不同的構造參數,所以需要根據參數來鎖定構造函數並完成初始化,如果存在參數則使用相應的帶有參數的構造函數,否則使用默認構造函數。

下面就上面四種情況做分別說明。

obtainFromSupplier()

Supplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {    return obtainFromSupplier(instanceSupplier, beanName);}

首先從 BeanDefinition 中獲取 Supplier,如果不爲空,則調用 obtainFromSupplier() 。那麼 Supplier 是什麼呢?在這之前也沒有提到過這個字段。

public interface Supplier<T> {    T get();}

Supplier 接口僅有一個功能性的 get(),該方法會返回一個 T 類型的對象,有點兒類似工廠方法。這個接口有什麼作用?用於指定創建 bean 的回調,如果我們設置了這樣的回調,那麼其他的構造器或者工廠方法都會沒有用。在什麼設置該參數呢?Spring 提供了相應的 setter 方法,如下:

    public void setInstanceSupplier(@Nullable Supplier<?> instanceSupplier) {        this.instanceSupplier = instanceSupplier;    }

在構造 BeanDefinition 的時候設置了該值,如下(以 RootBeanDefinition 爲例):

    public <T> RootBeanDefinition(@Nullable Class<T> beanClass, String scope, @Nullable Supplier<T> instanceSupplier) {        super();        setBeanClass(beanClass);        setScope(scope);        setInstanceSupplier(instanceSupplier);    }

如果設置了 instanceSupplier 則調用 obtainFromSupplier() 完成 bean 的初始化,如下:

    protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {        String outerBean = this.currentlyCreatedBean.get();        this.currentlyCreatedBean.set(beanName);        Object instance;        try {          // 調用 Supplier 的 get(),返回一個對象            instance = instanceSupplier.get();        }        finally {            if (outerBean != null) {                this.currentlyCreatedBean.set(outerBean);            }            else {                this.currentlyCreatedBean.remove();            }        }        // 根據對象構造 BeanWrapper 對象        BeanWrapper bw = new BeanWrapperImpl(instance);        // 初始化 BeanWrapper        initBeanWrapper(bw);        return bw;    }

代碼很簡單,調用 調用 Supplier 的 get() 方法,獲得一個 bean 實例對象,然後根據該實例對象構造一個 BeanWrapper 對象 bw,最後初始化該對象。有關於 BeanWrapper 後面專門出文講解。

instantiateUsingFactoryMethod()

如果存在工廠方法,則調用 instantiateUsingFactoryMethod() 完成 bean 的初始化工作(方法實現比較長,細節比較複雜,各位就硬着頭皮看吧)。

    protected BeanWrapper instantiateUsingFactoryMethod(            String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {        return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);    }

構造一個 ConstructorResolver 對象,然後調用其 instantiateUsingFactoryMethod() 方法。ConstructorResolver 是構造方法或者工廠類初始化 bean 的委託類。

      public BeanWrapper instantiateUsingFactoryMethod(            final String beanName, final RootBeanDefinition mbd, @Nullable final Object[] explicitArgs) {        // 構造 BeanWrapperImpl 對象        BeanWrapperImpl bw = new BeanWrapperImpl();        // 初始化 BeanWrapperImpl        // 向BeanWrapper對象中添加 ConversionService 對象和屬性編輯器 PropertyEditor 對象        //        this.beanFactory.initBeanWrapper(bw);        Object factoryBean;        Class<?> factoryClass;        boolean isStatic;        // 工廠名不爲空        String factoryBeanName = mbd.getFactoryBeanName();        if (factoryBeanName != null) {            if (factoryBeanName.equals(beanName)) {                throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,                        "factory-bean reference points back to the same bean definition");            }            // 獲取工廠實例            factoryBean = this.beanFactory.getBean(factoryBeanName);            if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {                throw new ImplicitlyAppearedSingletonException();            }            factoryClass = factoryBean.getClass();            isStatic = false;        }        else {            // 工廠名爲空,則其可能是一個靜態工廠            // 靜態工廠創建bean,必須要提供工廠的全類名            if (!mbd.hasBeanClass()) {                throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,                        "bean definition declares neither a bean class nor a factory-bean reference");            }            factoryBean = null;            factoryClass = mbd.getBeanClass();            isStatic = true;        }        // 工廠方法        Method factoryMethodToUse = null;        ConstructorResolver.ArgumentsHolder argsHolderToUse = null;        // 參數        Object[] argsToUse = null;        // 工廠方法的參數        // 如果指定了構造參數則直接使用        // 在調用 getBean 方法的時候指定了方法參數        if (explicitArgs != null) {            argsToUse = explicitArgs;        }        else {            // 沒有指定,則嘗試從配置文件中解析            Object[] argsToResolve = null;            // 首先嚐試從緩存中獲取            synchronized (mbd.constructorArgumentLock) {                // 獲取緩存中的構造函數或者工廠方法                factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;                if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {                    // 獲取緩存中的構造參數                    argsToUse = mbd.resolvedConstructorArguments;                    if (argsToUse == null) {                        // 獲取緩存中的構造函數參數的包可見字段                        argsToResolve = mbd.preparedConstructorArguments;                    }                }            }            // 緩存中存在,則解析存儲在 BeanDefinition 中的參數            // 如給定方法的構造函數 A(int ,int ),則通過此方法後就會把配置文件中的("1","1")轉換爲 (1,1)            // 緩存中的值可能是原始值也有可能是最終值            if (argsToResolve != null) {                argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve);            }        }        //        if (factoryMethodToUse == null || argsToUse == null) {            // 獲取工廠方法的類全名稱            factoryClass = ClassUtils.getUserClass(factoryClass);            // 獲取所有待定方法            Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);            // 檢索所有方法,這裏是對方法進行過濾            List<Method> candidateSet = new ArrayList<>();            for (Method candidate : rawCandidates) {                // 如果有static 且爲工廠方法,則添加到 candidateSet 中                if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {                    candidateSet.add(candidate);                }            }            Method[] candidates = candidateSet.toArray(new Method[0]);            // 排序構造函數            // public 構造函數優先參數數量降序,非public 構造函數參數數量降序            AutowireUtils.sortFactoryMethods(candidates);            // 用於承載解析後的構造函數參數的值            ConstructorArgumentValues resolvedValues = null;            boolean autowiring = (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);            int minTypeDiffWeight = Integer.MAX_VALUE;            Set<Method> ambiguousFactoryMethods = null;            int minNrOfArgs;            if (explicitArgs != null) {                minNrOfArgs = explicitArgs.length;            }            else {                // getBean() 沒有傳遞參數,則需要解析保存在 BeanDefinition 構造函數中指定的參數                if (mbd.hasConstructorArgumentValues()) {                    // 構造函數的參數                    ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();                    resolvedValues = new ConstructorArgumentValues();                    // 解析構造函數的參數                    // 將該 bean 的構造函數參數解析爲 resolvedValues 對象,其中會涉及到其他 bean                    minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);                }                else {                    minNrOfArgs = 0;                }            }            LinkedList<UnsatisfiedDependencyException> causes = null;            for (Method candidate : candidates) {                // 方法體的參數                Class<?>[] paramTypes = candidate.getParameterTypes();                if (paramTypes.length >= minNrOfArgs) {                    // 保存參數的對象                    ArgumentsHolder argsHolder;                    // getBean()傳遞了參數                    if (explicitArgs != null){                        // 顯示給定參數,參數長度必須完全匹配                        if (paramTypes.length != explicitArgs.length) {                            continue;                        }                        // 根據參數創建參數持有者                        argsHolder = new ArgumentsHolder(explicitArgs);                    }                    else {                        // 爲提供參數,解析構造參數                        try {                            String[] paramNames = null;                            // 獲取 ParameterNameDiscoverer 對象                            // ParameterNameDiscoverer 是用於解析方法和構造函數的參數名稱的接口,爲參數名稱探測器                            ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();                            if (pnd != null) {                                // 獲取指定構造函數的參數名稱                                paramNames = pnd.getParameterNames(candidate);                            }                            // 在已經解析的構造函數參數值的情況下,創建一個參數持有者對象                            argsHolder = createArgumentArray(                                    beanName, mbd, resolvedValues, bw, paramTypes, paramNames, candidate, autowiring);                        }                        catch (UnsatisfiedDependencyException ex) {                            if (this.beanFactory.logger.isTraceEnabled()) {                                this.beanFactory.logger.trace("Ignoring factory method [" + candidate +                                        "] of bean '" + beanName + "': " + ex);                            }                            if (causes == null) {                                causes = new LinkedList<>();                            }                            causes.add(ex);                            continue;                        }                    }                    // isLenientConstructorResolution 判斷解析構造函數的時候是否以寬鬆模式還是嚴格模式                    // 嚴格模式:解析構造函數時,必須所有的都需要匹配,否則拋出異常                    // 寬鬆模式:使用具有"最接近的模式"進行匹配                    // typeDiffWeight:類型差異權重                    int typeDiffWeight = (mbd.isLenientConstructorResolution() ?                            argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));                    // 代表最接近的類型匹配,則選擇作爲構造函數                    if (typeDiffWeight < minTypeDiffWeight) {                        factoryMethodToUse = candidate;                        argsHolderToUse = argsHolder;                        argsToUse = argsHolder.arguments;                        minTypeDiffWeight = typeDiffWeight;                        ambiguousFactoryMethods = null;                    }                    // 如果具有相同參數數量的方法具有相同的類型差異權重,則收集此類型選項                    // 但是,僅在非寬鬆構造函數解析模式下執行該檢查,並顯式忽略重寫方法(具有相同的參數簽名)                    else if (factoryMethodToUse != null && typeDiffWeight == minTypeDiffWeight &&                            !mbd.isLenientConstructorResolution() &&                            paramTypes.length == factoryMethodToUse.getParameterCount() &&                            !Arrays.equals(paramTypes, factoryMethodToUse.getParameterTypes())) {                        // 查找到多個可匹配的方法                        if (ambiguousFactoryMethods == null) {                            ambiguousFactoryMethods = new LinkedHashSet<>();                            ambiguousFactoryMethods.add(factoryMethodToUse);                        }                        ambiguousFactoryMethods.add(candidate);                    }                }            }            // 沒有可執行的工廠方法,拋出異常            if (factoryMethodToUse == null) {                if (causes != null) {                    UnsatisfiedDependencyException ex = causes.removeLast();                    for (Exception cause : causes) {                        this.beanFactory.onSuppressedException(cause);                    }                    throw ex;                }                List<String> argTypes = new ArrayList<>(minNrOfArgs);                if (explicitArgs != null) {                    for (Object arg : explicitArgs) {                        argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");                    }                }                else if (resolvedValues != null){                    Set<ConstructorArgumentValues.ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());                    valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());                    valueHolders.addAll(resolvedValues.getGenericArgumentValues());                    for (ConstructorArgumentValues.ValueHolder value : valueHolders) {                        String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :                                (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));                        argTypes.add(argType);                    }                }                String argDesc = StringUtils.collectionToCommaDelimitedString(argTypes);                throw new BeanCreationException(mbd.getResourceDescription(), beanName,                        "No matching factory method found: " +                                (mbd.getFactoryBeanName() != null ?                                        "factory bean '" + mbd.getFactoryBeanName() + "'; " : "") +                                "factory method '" + mbd.getFactoryMethodName() + "(" + argDesc + ")'. " +                                "Check that a method with the specified name " +                                (minNrOfArgs > 0 ? "and arguments " : "") +                                "exists and that it is " +                                (isStatic ? "static" : "non-static") + ".");            }            else if (void.class == factoryMethodToUse.getReturnType()) {                throw new BeanCreationException(mbd.getResourceDescription(), beanName,                        "Invalid factory method '" + mbd.getFactoryMethodName() +                                "': needs to have a non-void return type!");            }            else if (ambiguousFactoryMethods != null) {                throw new BeanCreationException(mbd.getResourceDescription(), beanName,                        "Ambiguous factory method matches found in bean '" + beanName + "' " +                                "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +                                ambiguousFactoryMethods);            }            if (explicitArgs == null && argsHolderToUse != null) {                // 將解析的構造函數加入緩存                argsHolderToUse.storeCache(mbd, factoryMethodToUse);            }        }        try {            // 實例化 bean            Object beanInstance;            if (System.getSecurityManager() != null) {                final Object fb = factoryBean;                final Method factoryMethod = factoryMethodToUse;                final Object[] args = argsToUse;                // 通過執行工廠方法來創建bean示例                beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->                                beanFactory.getInstantiationStrategy().instantiate(mbd, beanName, beanFactory, fb, factoryMethod, args),                        beanFactory.getAccessControlContext());            }            else {                // 通過執行工廠方法來創建bean示例                beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(                        mbd, beanName, this.beanFactory, factoryBean, factoryMethodToUse, argsToUse);            }            // 包裝爲 BeanWraper 對象            bw.setBeanInstance(beanInstance);            return bw;        }        catch (Throwable ex) {            throw new BeanCreationException(mbd.getResourceDescription(), beanName,                    "Bean instantiation via factory method failed", ex);        }    }

instantiateUsingFactoryMethod() 方法體實在是太大了,處理細節感覺很複雜,LZ是硬着頭皮看完的,中間斷斷續續的。吐槽這裏的代碼風格,完全不符合我們前面看的 Spring 代碼風格。Spring 的一貫做法是將一個複雜邏輯進行拆分,分爲多個細小的模塊進行嵌套,每個模塊負責一部分功能,模塊與模塊之間層層嵌套,上一層一般都是對下一層的總結和概括,這樣就會使得每一層的邏輯變得清晰易懂。

迴歸到上面的方法體,雖然代碼體量大,但是總體我們還是可看清楚這個方法要做的事情。一句話概括就是:確定工廠對象,然後獲取構造函數和構造參數,最後調用 InstantiationStrategy 對象的 instantiate() 來創建 bean 實例。下面我們就這個句概括的話進行拆分並詳細說明。

確定工廠對象

首先獲取工廠方法名,若工廠方法名不爲空,則調用 beanFactory.getBean() 獲取工廠對象,若爲空,則可能爲一個靜態工廠,對於靜態工廠則必須提供工廠類的全類名,同時設置 factoryBean=null

構造參數確認

工廠對象確定後,則是確認構造參數。構造參數的確認主要分爲三種情況:explicitArgs 參數、緩存中獲取、配置文件中解析。

explicitArgs 參數

explicitArgs 參數是我們調用 getBean() 時傳遞景來,一般該參數,該參數就是用於初始化 bean 時所傳遞的參數,如果該參數不爲空,則可以確定構造函數的參數就是它了。

緩存中獲取

在該方法的最後,我們會發現這樣一段代碼: argsHolderToUse.storeCache(mbd,factoryMethodToUse) ,這段代碼主要是將構造函數、構造參數保存到緩存中,如下:

        public void storeCache(RootBeanDefinition mbd, Executable constructorOrFactoryMethod) {            synchronized (mbd.constructorArgumentLock) {                mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;                mbd.constructorArgumentsResolved = true;                if (this.resolveNecessary) {                    mbd.preparedConstructorArguments = this.preparedArguments;                }                else {                    mbd.resolvedConstructorArguments = this.arguments;                }            }        }

其中涉及到的幾個參數 constructorArgumentLock、resolvedConstructorOrFactoryMethod、constructorArgumentsResolved、resolvedConstructorArguments。這些參數都是跟構造函數、構造函數緩存有關的。

  • constructorArgumentLock:構造函數的緩存鎖
  • resolvedConstructorOrFactoryMethod:緩存已經解析的構造函數或者工廠方法
  • constructorArgumentsResolved:標記字段,標記構造函數、參數已經解析了。默認爲false
  • resolvedConstructorArguments:緩存已經解析的構造函數參數,包可見字段

所以從緩存中獲取就是提取這幾個參數的值,如下:

            synchronized (mbd.constructorArgumentLock) {                // 獲取緩存中的構造函數或者工廠方法                factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;                if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {                    // 獲取緩存中的構造參數                    argsToUse = mbd.resolvedConstructorArguments;                    if (argsToUse == null) {                        // 獲取緩存中的構造函數參數的包可見字段                        argsToResolve = mbd.preparedConstructorArguments;                    }                }            }

如果緩存中存在構造參數,則需要調用 resolvePreparedArguments() 方法進行轉換,因爲緩存中的值有可能是最終值也有可能不是最終值,比如我們構造函數中的類型爲 Integer 類型的 1 ,但是原始的參數類型有可能是 String 類型的 1 ,所以即便是從緩存中得到了構造參數也需要經過一番的類型轉換確保參數類型完全對應。

配置文件中解析

即沒有通過傳遞參數的方式傳遞構造參數,緩存中也沒有,那就只能通過解析配置文件獲取構造參數了。

在 bean 解析類的博文中我們瞭解了,配置文件中的信息都會轉換到 BeanDefinition 實例對象中,所以配置文件中的參數可以直接通過 BeanDefinition 對象獲取。代碼如下:

if (mbd.hasConstructorArgumentValues()) {    // 構造函數的參數    ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();    resolvedValues = new ConstructorArgumentValues();    // 解析構造函數的參數    // 將該 bean 的構造函數參數解析爲 resolvedValues 對象,其中會涉及到其他 bean    minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);}

通過 BeanDefinition 的 getConstructorArgumentValues() 就可以獲取構造信息了,有了構造信息就可以獲取相關的參數值信息了,獲取的參數信息包括直接值和引用,這一步驟的處理交由 resolveConstructorArguments()完成,該方法會將構造參數信息解析爲 resolvedValues 對象 並返回解析到的參數個數。

構造函數

確定構造參數後,下一步則是確定構造函數。第一步則是通過 getCandidateMethods() 獲取所有的構造方法,同時對構造方法進行刷選,然後在對其進行排序處理( AutowireUtils.sortFactoryMethods(candidates)),排序的主要目的是爲了能夠更加方便的找到匹配的構造函數,因爲構造函數的確認是根據參數個數確認的。排序的規則是:public 構造函數優先參數數量降序、非 public 構造參數數量降序。

通過迭代 candidates(包含了所有要匹配的構造函數)的方式,一次比較其參數,如果顯示提供了參數(explicitArgs != null),則直接比較兩者是否相等,如果相等則表示找到了,否則繼續比較。如果沒有顯示提供參數,則需要獲取 ParameterNameDiscoverer 對象,該對象爲參數名稱探測器,主要用於發現方法和構造函數的參數名稱。

將參數包裝成 ArgumentsHolder 對象,該對象用於保存參數,我們稱之爲參數持有者。當將對象包裝成 ArgumentsHolder 對象後,我們就可以通過它來進行構造函數匹配,匹配分爲嚴格模式和寬鬆模式。

  • 嚴格模式:解析構造函數時,必須所有參數都需要匹配,否則拋出異常
  • 寬鬆模式:使用具有"最接近的模式"進行匹配

判斷的依據是根據 BeanDefinition 的 isLenientConstructorResolution 屬性(該參數是我們在構造 AbstractBeanDefinition 對象是傳遞的)來獲取類型差異權重(typeDiffWeight) 的。如果 typeDiffWeight<minTypeDiffWeight ,則代表“最接近的模式”,選擇其作爲構造函數,否則只有兩者具有相同的參數數量且類型差異權重相等纔會納入考慮範圍。

至此,構造函數已經確認了。

創建 bean 實例

工廠對象、構造函數、構造參數都已經確認了,則最後一步就是調用 InstantiationStrategy 對象的 instantiate() 來創建 bean 實例,如下:

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,            @Nullable Object factoryBean, final Method factoryMethod, @Nullable Object... args) {        try {            if (System.getSecurityManager() != null) {                AccessController.doPrivileged((PrivilegedAction<Object>) () -> {                    ReflectionUtils.makeAccessible(factoryMethod);                    return null;                });            }            else {                ReflectionUtils.makeAccessible(factoryMethod);            }            Method priorInvokedFactoryMethod = currentlyInvokedFactoryMethod.get();            try {                currentlyInvokedFactoryMethod.set(factoryMethod);                // 執行工廠方法,並返回實例                Object result = factoryMethod.invoke(factoryBean, args);                if (result == null) {                    result = new NullBean();                }                return result;            }            finally {                if (priorInvokedFactoryMethod != null) {                    currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);                }                else {                    currentlyInvokedFactoryMethod.remove();                }            }        }        // 省略一波 catch    }

instantiate() 最核心的部分就是利用 Java 反射執行工廠方法並返回創建好的實例,也就是這段代碼:

Object result = factoryMethod.invoke(factoryBean, args);

到這裏 instantiateUsingFactoryMethod() 已經分析完畢了,這裏 LZ 有些題外話需要說下,看源碼真心是一個痛苦的過程,尤其是複雜的源碼,比如這個方法我看了三天才弄清楚點皮毛,當然這裏跟 LZ 的智商有些關係(智商捉急 ┭┮﹏┭┮),寫這篇博客也花了五天時間才寫完(最後截稿日爲:2018.08.10 01:23:49),所以每一個堅持寫博客的都是折翼的天使,值得各位尊敬

createBeanInstance() 還有兩個重要方法 autowireConstructor()instantiateBean() ,由於篇幅問題,所以將這兩個方法放在下篇博客分析。敬請期待!!!

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