spring容器之創(chuàng)建bean實例

在上篇spring容器之開啟bean的創(chuàng)建之旅中我們最后將創(chuàng)建bean的過程大致的總結了分八步走,這里就不啰嗦了,不知道的可以自己去看看,本篇主要的學習是對上節(jié)創(chuàng)建bean的每個步驟進行詳細的學習,首先我們從創(chuàng)建bean的實例開始,代碼如下:

AbstractAutowireCapableBeanFactory.java

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.
    //解析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());
    }
    //<1>.獲取創(chuàng)建bean實例的回調Supplier
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    //如果存在該回調,使用該回調策略來初始化bean實例
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }
    //<2>.如果工廠方法不為null,則使用工廠的方法的策略來初始化bean實例
    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    //<3>. Shortcut when re-creating the same bean...
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        //使用constructorArgumentLock
        //該constructorArgumentLock為構造函數(shù)字段常用的鎖
        synchronized (mbd.constructorArgumentLock) {
            //<3.1>.resolvedConstructorOrFactoryMethod用來緩存已解析的構造函數(shù)的字段和或工廠方法
            //如果不為null
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                //對該構造參數(shù)進行標記為已解析
                //因為對于一個類可能有很多個構造函數(shù),每個構造函數(shù)所需的參數(shù)可能不一樣,所以在調用前需確定其參數(shù)方可
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    //如果解析完成,直接通過注入即可
    if (resolved) {
        //<3.2>.構造函數(shù)自動注入
        if (autowireNecessary) {
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            //<3.3>.使用默認構造函數(shù)進行構造
            return instantiateBean(beanName, mbd);
        }
    }

    // Candidate constructors for autowiring?
    //<4>.通過參數(shù)來解析構造器
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    //<4.1>.當args不為null時,通過參數(shù)的個數(shù),類型等,做精確的構造方法的選擇來創(chuàng)建bean
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // Preferred constructors for default construction?
    //<4.2>.獲取構造方法來構建bean
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
        return autowireConstructor(beanName, mbd, ctors, null);
    }

    // No special handling: simply use no-arg constructor.
    //<4.3>.使用默認的構造函數(shù)構造
    return instantiateBean(beanName, mbd);
}

方法很長,但總體來說目的很明確,這里簡單的小結一下:

  • 在<1>處,我們可以看到對創(chuàng)建bean實例過程中回調的獲取
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    //如果存在該回調,使用該回調策略來初始化bean實例
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }

當獲取到的回調不為null時,發(fā)現(xiàn)調用#obtainFromSupplier(Supplier<?> instanceSupplier, String beanName)來初始化,跟蹤代碼來到:

看代碼之前先來了解一個java8里的特性Supplier<?>接口的東西,讓大家有個認識,說實話好久沒接觸過了,直接看代碼:

@FunctionalInterface
public interface Supplier<T> {

/**
 * Gets a result.
 *
 * @return a result
 */
T get();

}

Supplier實際上是一個供給接口,且只有一個get()方法,其實類似于spring的工廠方法.

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

/**
 * Return a callback for creating an instance of the bean, if any.
 * @since 5.0
 */
@Nullable
public Supplier<?> getInstanceSupplier() {
    return this.instanceSupplier;
}

在AbstractBeanDefinition類中可以看到它的實例化過程,接下來我們來看回調的整個過程:

/**保存當前創(chuàng)建bean的名字*/
private final NamedThreadLocal<String> currentlyCreatedBean = new NamedThreadLocal<>("Currently created bean");


protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
    Object instance;
    //獲取原先創(chuàng)建bean的名字
    String outerBean = this.currentlyCreatedBean.get();
    //保存新的bean的名字到currentlyCreatedBean中
    this.currentlyCreatedBean.set(beanName);
    try {
        //1.調用Supplier#get()方法獲取bean實例
        instance = instanceSupplier.get();
    }
    finally {
        if (outerBean != null) {
            //如果原先bean存在,將保存到currentlyCreatedBean中
            this.currentlyCreatedBean.set(outerBean);
        }
        else {
            this.currentlyCreatedBean.remove();
        }
    }
    //2.如果沒有創(chuàng)建對象時,則創(chuàng)建一個NullBean實例
    if (instance == null) {
        instance = new NullBean();
    }
    //3.初始化BeanWrapper對象
    BeanWrapper bw = new BeanWrapperImpl(instance);
    initBeanWrapper(bw);
    return bw;
}

簡單的總結一下:

  • 調用我們指定的Supplier的get()方法獲取bean的實例
  • 進行一些相關的設置操作
  • 如果沒有創(chuàng)建對象,直接創(chuàng)建一個NullBean對象.
  • 最后是對BeanWrapper對象的創(chuàng)建以及初始化的操作
  • 在<2>處,我們可以看到的是,如果存在工廠方法,則通過#instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs)方法來完成bean的初始化過程,直接看代碼:
AbstractAutowireCapableBeanFactory.java

protected BeanWrapper instantiateUsingFactoryMethod(
        String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {

    return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}

我們可以方法首先需要構造一個ConstructorResolver對象,然后調用該實例的#instantiateUsingFactoryMethod(String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs)方法構建bean實例,接著看:

ConstructorResolver.java
public BeanWrapper instantiateUsingFactoryMethod(
        String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    //1.構建并實例化BeanWrapperImpl對象
    BeanWrapperImpl bw = new BeanWrapperImpl();
    this.beanFactory.initBeanWrapper(bw);
    //2.獲取factoryBean factoryClass和isStatic等屬性
    Object factoryBean;
    Class<?> factoryClass;
    boolean isStatic;
    //2.1.獲取factoryBeanName屬性
    String factoryBeanName = mbd.getFactoryBeanName();
    //factoryBeanName存在,且跟當前bean的名字一樣,直接拋BeanDefinitionStoreException異常
    if (factoryBeanName != null) {
        if (factoryBeanName.equals(beanName)) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
                    "factory-bean reference points back to the same bean definition");
        }
        //不一樣的情況下
        //2.2.獲取factory實例
        factoryBean = this.beanFactory.getBean(factoryBeanName);

        if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
            throw new ImplicitlyAppearedSingletonException();
        }
        //2.3.獲取factoryClass屬性
        factoryClass = factoryBean.getClass();
        isStatic = false;
    }
    //2.3.此處可能是靜態(tài)工廠方法
    //因為靜態(tài)工廠創(chuàng)建bean時,需要提供工廠的全類名
    else {
        // It's a static factory method on the bean class.
        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;
    }
    //3.獲取工廠屬性factoryMethodToUse ArgumentsHolder和argsToUse

    Method factoryMethodToUse = null;//工廠方法
    ArgumentsHolder argsHolderToUse = null;
    Object[] argsToUse = null;//參數(shù)
    //3.1.explicitArgs參數(shù)通過getBean方法傳入
    //如果在構建bean時指定了構造器,那么直接使用該參數(shù)
    if (explicitArgs != null) {
        argsToUse = explicitArgs;
    }
    //3.2.沒有指定的話,嘗試著從配置文件中解析
    else {
        Object[] argsToResolve = null;
        //給公用構造方法加鎖
        synchronized (mbd.constructorArgumentLock) {
            //從緩存中嘗試著獲取
            factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
            //從緩存中獲取argsToUse屬性
            if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
                // Found a cached factory method...
                argsToUse = mbd.resolvedConstructorArguments;
                //從緩存中沒有獲取到
                if (argsToUse == null) {
                    //獲取構造函數(shù)的可見字段
                    argsToResolve = mbd.preparedConstructorArguments;
                }
            }
        }
        //3.3.緩存中存在
        //解析在beanDefinition中的參數(shù)類型,解析的過程大致如下:
        //如給定方法的構造函數(shù) A(int ,int ),則通過此方法后就會把配置文件中的("1","1")轉換為 (1,1)
        //緩存中的值可能是原始值也有可能是最終值
        if (argsToResolve != null) {
            argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
        }
    }

    //4.沒有被緩存
    if (factoryMethodToUse == null || argsToUse == null) {
        // Need to determine the factory method...
        // Try all methods with this name to see if they match the given arguments.
        //4.1.獲取全限定名
        factoryClass = ClassUtils.getUserClass(factoryClass);

        List<Method> candidateList = null;
        //4.2.檢測方法名是否是唯一性
        if (mbd.isFactoryMethodUnique) {
            if (factoryMethodToUse == null) {
                factoryMethodToUse = mbd.getResolvedFactoryMethod();
            }
            if (factoryMethodToUse != null) {
                candidateList = Collections.singletonList(factoryMethodToUse);
            }
        }
        if (candidateList == null) {
            candidateList = new ArrayList<>();
            //4.3.獲取所有符合條件的方法
            Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
            //遍歷符合條件是static的方法那么就添加到candidateList中
            for (Method candidate : rawCandidates) {
                if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
                    candidateList.add(candidate);
                }
            }
        }

        //4.4創(chuàng)建bean實例
        if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
            Method uniqueCandidate = candidateList.get(0);
            if (uniqueCandidate.getParameterCount() == 0) {
                //緩存內(nèi)省工廠方法
                mbd.factoryMethodToIntrospect = uniqueCandidate;
                synchronized (mbd.constructorArgumentLock) {
                    mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
                    mbd.constructorArgumentsResolved = true;
                    mbd.resolvedConstructorArguments = EMPTY_ARGS;
                }
                //封裝bean
                bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
                return bw;
            }
        }

        Method[] candidates = candidateList.toArray(new Method[0]);
        //對構造的工廠方法進行排序
        //排序規(guī)則是:優(yōu)先是public的,之后是非公共的
        AutowireUtils.sortFactoryMethods(candidates);

        ConstructorArgumentValues resolvedValues = null;
        boolean autowiring = (mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
        int minTypeDiffWeight = Integer.MAX_VALUE;
        Set<Method> ambiguousFactoryMethods = null;

        int minNrOfArgs;
        if (explicitArgs != null) {
            minNrOfArgs = explicitArgs.length;
        }
        else {
            // We don't have arguments passed in programmatically, so we need to resolve the
            // arguments specified in the constructor arguments held in the bean definition.
            //4.5.獲取構造函數(shù)的參數(shù)
            if (mbd.hasConstructorArgumentValues()) {
                ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
                //用來承載解析后的參數(shù)的值
                resolvedValues = new ConstructorArgumentValues();
                //解析參數(shù)
                minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
            }
            else {
                minNrOfArgs = 0;
            }
        }
        //4.6.遍歷方法
        LinkedList<UnsatisfiedDependencyException> causes = null;

        for (Method candidate : candidates) {
            //獲取方法體上的參數(shù)
            Class<?>[] paramTypes = candidate.getParameterTypes();
            //
            if (paramTypes.length >= minNrOfArgs) {
                //保存參數(shù)對象
                ArgumentsHolder argsHolder;
                //explicitArgs為getBean方法的參數(shù)
                if (explicitArgs != null) {
                    // Explicit arguments given -> arguments length must match exactly.
                    //顯示給定參數(shù),參數(shù)的長度必須匹配
                    if (paramTypes.length != explicitArgs.length) {
                        continue;
                    }
                    //根據(jù)參數(shù)去構建參數(shù)的持有者ArgumentsHolder對象
                    argsHolder = new ArgumentsHolder(explicitArgs);
                }
                //構建bean的explicitArgs為null
                else {
                    // Resolved constructor arguments: type conversion and/or autowiring necessary.
                    //為了提供必須的參數(shù),解析參數(shù)
                    try {
                        String[] paramNames = null;
                        //獲取ParameterNameDiscoverer對象
                        //ParameterNameDiscoverer為解析方法和構造函數(shù)的參數(shù)的接口
                        ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                        //如果存在,獲取構造器的所有參數(shù)
                        if (pnd != null) {
                            paramNames = pnd.getParameterNames(candidate);
                        }
                        //在給定已解析的構造函數(shù)參數(shù)值的情況下,創(chuàng)建一個參數(shù)ArgumentsHolder的持有者對象
                        argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw,
                                paramTypes, paramNames, candidate, autowiring, candidates.length == 1);
                    }
                    //在創(chuàng)建的過程中,如果拋UnsatisfiedDependencyException異常,保存到causes中
                    catch (UnsatisfiedDependencyException ex) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("Ignoring factory method [" + candidate + "] of bean '" + beanName + "': " + ex);
                        }
                        // Swallow and try next overloaded factory method.
                        if (causes == null) {
                            causes = new LinkedList<>();
                        }
                        causes.add(ex);
                        //繼續(xù)執(zhí)行
                        continue;
                    }
                }

                //5.通過isLenientConstructorResolution來判斷解析的構造方法是寬松模式還是嚴格模式
                //如果是寬松模式:采用最接近的來匹配解析
                //如果是嚴格模式:所有的都要匹配上才可以
                //typeDiffWeight:獲取類型差異權重
                int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
                        argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
                // Choose this factory method if it represents the closest match.
                //匹配最接近的構造函數(shù),以下為作為該構造函數(shù)的參數(shù)
                if (typeDiffWeight < minTypeDiffWeight) {
                    factoryMethodToUse = candidate;
                    argsHolderToUse = argsHolder;
                    argsToUse = argsHolder.arguments;
                    minTypeDiffWeight = typeDiffWeight;
                    ambiguousFactoryMethods = null;
                }
                // Find out about ambiguity: In case of the same type difference weight
                // for methods with the same number of parameters, collect such candidates
                // and eventually raise an ambiguity exception.
                // However, only perform that check in non-lenient constructor resolution mode,
                // and explicitly ignore overridden methods (with the same parameter signature).
                // 如果具有相同參數(shù)數(shù)量的方法具有相同的類型差異權重,則收集此類型選項
                // 但是,僅在非寬松構造函數(shù)解析模式下執(zhí)行該檢查,并顯式忽略重寫方法(具有相同的參數(shù)簽名)
                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);
                }
            }
        }

        //6. 沒有可執(zhí)行的方法時,直接拋UnsatisfiedDependencyException異常
        if (factoryMethodToUse == null || argsToUse == null) {
            if (causes != null) {
                UnsatisfiedDependencyException ex = causes.removeLast();
                for (Exception cause : causes) {
                    this.beanFactory.onSuppressedException(cause);
                }
                throw ex;
            }
            List<String> argTypes = new ArrayList<>(minNrOfArgs);
            //遍歷explicitArgs參數(shù)數(shù)組
            if (explicitArgs != null) {
                for (Object arg : explicitArgs) {
                    //如果遍歷到的參數(shù)不為null,獲取參數(shù)名,然后保存,為null,直接保存null即可
                    argTypes.add(arg != null ? arg.getClass().getSimpleName() : "null");
                }
            }
            else if (resolvedValues != null) {
                Set<ValueHolder> valueHolders = new LinkedHashSet<>(resolvedValues.getArgumentCount());
                valueHolders.addAll(resolvedValues.getIndexedArgumentValues().values());
                valueHolders.addAll(resolvedValues.getGenericArgumentValues());
                for (ValueHolder value : valueHolders) {
                    String argType = (value.getType() != null ? ClassUtils.getShortName(value.getType()) :
                            (value.getValue() != null ? value.getValue().getClass().getSimpleName() : "null"));
                    argTypes.add(argType);
                }
            }
            //對argTypes進行轉換
            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);
        }
        //將解析后的構造函數(shù)保存到緩存中

        if (explicitArgs == null && argsHolderToUse != null) {
            mbd.factoryMethodToIntrospect = factoryMethodToUse;
            argsHolderToUse.storeCache(mbd, factoryMethodToUse);
        }
    }
    //創(chuàng)建bean對象,并保存到bw中
    bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, factoryMethodToUse, argsToUse));
    return bw;
}

嗚嗚嗚,這個方法好長呀,看的也是懵逼,硬著頭皮看的,而且過程也很復雜,我看完之后也沒啥影響了,再來一遍,好像在方法的整個過程中,都是對工廠對象的構造函數(shù)和參數(shù)展開,通過匹配最接近的構造函數(shù),在方法的末尾調用#instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner, Constructor<?> ctor, Object... args) 方法來建bean對象.我們在對該方法進行總結一下:

  • 在1.處是首先是對BeanWrapperImpl對象的創(chuàng)建和初始化,以備后面bean的創(chuàng)建完成后進行封裝
  • 在2.處,獲取工廠bean的一些參數(shù)和方法,如:factoryBeanName和factoryClass和isStatic等屬性
  • 在2.1.處是對factoryBeanName的獲取以及簡單的處理操作
    String factoryBeanName = mbd.getFactoryBeanName();
    //factoryBeanName存在,且跟當前bean的名字一樣,直接拋BeanDefinitionStoreException異常
    if (factoryBeanName != null) {
        if (factoryBeanName.equals(beanName)) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
                    "factory-bean reference points back to the same bean definition");
        }

我們可以看到是通過beanDefinition來獲取factoryBean的name屬性,這也是符合的,我們知道beanDefinition就是描述一個bean的定義

  • 在2.2.處是獲取factory實例
factoryBean = this.beanFactory.getBean(factoryBeanName);

        if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
            throw new ImplicitlyAppearedSingletonException();
        }

是通過#getBean()來獲取的,此方法最后是通過AbstractAutowireCapableBeanFactory#getBean(String name)來實現(xiàn),關于此方法的學習我們前面已經(jīng)說了,這里就不啰嗦了,這里我們需要注意的一點是:
上述獲取到的factory是因為工廠的方法不為null的情況下.再來看另外一種情況.

  • 2.3.處,那么就是一個靜態(tài)工廠了,需要提供類的全限定名才能獲取factory對象
  • 在3.處實際上是對工廠工造參數(shù)的確定,其主要是通過explicitArgs是否為null來判斷

注意:explicitArgs主要是我們在調用#getBean方法時,由用戶直接指定構造函數(shù)來創(chuàng)建對象的參數(shù),它不為null,那么我們的構造函數(shù)就確認了

  • 在3.2處,當explicitArgs為null時,從配置文件中解析獲取
.....省略很多代碼.....

Object[] argsToResolve = null;
        //給公用構造方法加鎖
        synchronized (mbd.constructorArgumentLock) {
            //從緩存中嘗試著獲取
            factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
            //從緩存中獲取argsToUse屬性
            if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
                // Found a cached factory method...
                argsToUse = mbd.resolvedConstructorArguments;
                //從緩存中沒有獲取到
                if (argsToUse == null) {
                    //獲取構造函數(shù)的可見字段
                    argsToResolve = mbd.preparedConstructorArguments;
                }
            }
        }

都是從我們的beanDefinition中嘗試著獲取,簡單的來說一下:

<1>. 首先是從resolvedConstructorOrFactoryMethod獲取,該緩存主要保存的是已經(jīng)解析過的構造方法或者是工廠方法
<2> . 從resolvedConstructorArguments中獲取已經(jīng)完全解析的構造函數(shù)的參數(shù)
<3>. 從preparedConstructorArguments中獲取已經(jīng)準備好的部分構造參數(shù)以備構造方法使用

  • 在3.3.處,上述的參數(shù)我們在緩存中獲取到了,解析部分構造函數(shù)所需的參數(shù),調用#resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,Executable executable, Object[] argsToResolve, boolean fallback)方法來完成
if (argsToResolve != null) {
            argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
        }

當argsToResolve存在的情況下,接著看:

private Object[] resolvePreparedArguments(String beanName, RootBeanDefinition mbd, BeanWrapper bw,
        Executable executable, Object[] argsToResolve, boolean fallback) {
    //獲取TypeConverter對象
    TypeConverter customConverter = this.beanFactory.getCustomTypeConverter();
    //存在的話,就用自定義的TypeConverter,不存在的話用BeanWrapper來代替
    TypeConverter converter = (customConverter != null ? customConverter : bw);
    //這里的beanFactory為AbstractAutowireCapableBeanFactory
    //構建BeanDefinitionValueResolver解析器
    BeanDefinitionValueResolver valueResolver =
            new BeanDefinitionValueResolver(this.beanFactory, beanName, mbd, converter);
    //獲取參數(shù)的類型
    Class<?>[] paramTypes = executable.getParameterTypes();
    //解析處理過程
    Object[] resolvedArgs = new Object[argsToResolve.length];
    for (int argIndex = 0; argIndex < argsToResolve.length; argIndex++) {
        Object argValue = argsToResolve[argIndex];
        //通過參數(shù)的索引和構造函數(shù)來創(chuàng)建MethodParameter對象
        MethodParameter methodParam = MethodParameter.forExecutable(executable, argIndex);
        //解析參數(shù)的類型
        GenericTypeResolver.resolveParameterType(methodParam, executable.getDeclaringClass());
        //argValue是AutowiredArgumentMarker
        //調用resolveAutowiredArgument去解析處理
        if (argValue instanceof AutowiredArgumentMarker) {
            argValue = resolveAutowiredArgument(methodParam, beanName, null, converter, fallback);
        }
        //如果是BeanMetadataElement類型的
        //調用resolveValueIfNecessary去解析處理
        else if (argValue instanceof BeanMetadataElement) {
            argValue = valueResolver.resolveValueIfNecessary("constructor argument", argValue);
        }
        //字符串類型的
        //通過AbstractAutowireCapableBeanFactory#evaluateBeanDefinitionString方法去處理
        else if (argValue instanceof String) {

            argValue = this.beanFactory.evaluateBeanDefinitionString((String) argValue, mbd);
        }
        //保存
        Class<?> paramType = paramTypes[argIndex];
        try {
            //對解析后的參數(shù)進行轉換
            //規(guī)則為:如給定方法的構造函數(shù) A(int ,int ),則通過此方法后就會把配置文件中的("1","1")轉換為 (1,1)
            resolvedArgs[argIndex] = converter.convertIfNecessary(argValue, paramType, methodParam);
        }
        catch (TypeMismatchException ex) {
            throw new UnsatisfiedDependencyException(
                    mbd.getResourceDescription(), beanName, new InjectionPoint(methodParam),
                    "Could not convert argument value of type [" + ObjectUtils.nullSafeClassName(argValue) +
                    "] to required type [" + paramType.getName() + "]: " + ex.getMessage());
        }
    }
    return resolvedArgs;
}

在該方法的最后我們發(fā)現(xiàn),對于不同類型的參數(shù)類型,對應著不同的處理方法.
最后進行參數(shù)的轉化

  • 在4處,如果工廠沒有被緩存,可能是靜態(tài)工廠
  • 4.1.處首先是獲取factory的全限定名并進行唯一性的檢查
  • 4.3.處獲取所有符合條件的方法
Method[] rawCandidates = getCandidateMethods(factoryClass, mbd);
//遍歷符合條件是static的方法那么就添加到candidateList中
  for (Method candidate : rawCandidates) {
    if (Modifier.isStatic(candidate.getModifiers()) == isStatic && mbd.isFactoryMethod(candidate)) {
                candidateList.add(candidate);
                }
            }
  • 在4.4處創(chuàng)建bean對象并封裝
  List<Method> candidateList = null;
if (candidateList.size() == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
            Method uniqueCandidate = candidateList.get(0);
            if (uniqueCandidate.getParameterCount() == 0) {
                //緩存內(nèi)省工廠方法
                mbd.factoryMethodToIntrospect = uniqueCandidate;
                synchronized (mbd.constructorArgumentLock) {
                    mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
                    mbd.constructorArgumentsResolved = true;
                    mbd.resolvedConstructorArguments = EMPTY_ARGS;
                }
                //封裝bean
                bw.setBeanInstance(instantiate(beanName, mbd, factoryBean, uniqueCandidate, EMPTY_ARGS));
                return bw;
            }
        }

在此處是創(chuàng)建bean實例的地方,核心方法#instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner, Object factoryBean, final Method factoryMethod, @Nullable Object... args)來創(chuàng)建,因為我們的工廠對象以及構造函數(shù)和參數(shù)已經(jīng)確定了,接著看:

private Object instantiate(String beanName, RootBeanDefinition mbd,
        @Nullable Object factoryBean, Method factoryMethod, Object[] args) {

    try {
        //首先是獲取當前系統(tǒng)的安全環(huán)境管理器
        //存在的話在當前環(huán)境下創(chuàng)建
        if (System.getSecurityManager() != null) {
            return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
                    this.beanFactory.getInstantiationStrategy().instantiate(
                            mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args),
                    this.beanFactory.getAccessControlContext());
        }
        //直接創(chuàng)建
        else {
            return this.beanFactory.getInstantiationStrategy().instantiate(
                    mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Bean instantiation via factory method failed", ex);
    }
}

我們可以發(fā)現(xiàn)首先是對系統(tǒng)的當前環(huán)境的檢測,如:是否有訪問權限等,然后真正的核心創(chuàng)建bean實例的方法是InstantiationStrategy#instantiate()方法,接著看:

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
        @Nullable Object factoryBean, final Method factoryMethod, 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中
            currentlyInvokedFactoryMethod.set(factoryMethod);
            //創(chuàng)建bean對象
            Object result = factoryMethod.invoke(factoryBean, args);
            //沒創(chuàng)建成功,則創(chuàng)建一個nullBean來代替
            if (result == null) {
                result = new NullBean();
            }
            //創(chuàng)建成功的話,直接返回
            return result;
        }
        finally {
            if (priorInvokedFactoryMethod != null) {
                //覆蓋之前的方法
                currentlyInvokedFactoryMethod.set(priorInvokedFactoryMethod);
            }
            else {
                currentlyInvokedFactoryMethod.remove();
            }
        }
    }
    catch (IllegalArgumentException ex) {
        throw new BeanInstantiationException(factoryMethod,
                "Illegal arguments to factory method '" + factoryMethod.getName() + "'; " +
                "args: " + StringUtils.arrayToCommaDelimitedString(args), ex);
    }
    catch (IllegalAccessException ex) {
        throw new BeanInstantiationException(factoryMethod,
                "Cannot access factory method '" + factoryMethod.getName() + "'; is it public?", ex);
    }
    catch (InvocationTargetException ex) {
        String msg = "Factory method '" + factoryMethod.getName() + "' threw exception";
        if (bd.getFactoryBeanName() != null && owner instanceof ConfigurableBeanFactory &&
                ((ConfigurableBeanFactory) owner).isCurrentlyInCreation(bd.getFactoryBeanName())) {
            msg = "Circular reference involving containing bean '" + bd.getFactoryBeanName() + "' - consider " +
                    "declaring the factory method as static for independence from its containing instance. " + msg;
        }
        throw new BeanInstantiationException(factoryMethod, msg, ex.getTargetException());
    }
}

該方法其實就一個核心點,通過反射的方式來創(chuàng)建對象

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

其實到這一步了我們的目標也達到了,后面的無非還是一些參數(shù)的驗證和匹配最接近的構造函數(shù),最后還是調用#instantiate來創(chuàng)建bean對象,其中包括一些解析參數(shù)的方法如:#resolveConstructorArguments()方法和#createBeanInstance(...)方法可以去看看,我這里就不說了,那么關于創(chuàng)建bean實例的篇幅就到這里了

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

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

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