Spring 源碼解析—創(chuàng)建 bean

創(chuàng)建 bean

在經(jīng)歷過 AbstractAutowireCapableBeanFactory#createBean 中的 resolveBeforeInstantiation 方法后奈辰,程序有兩個選擇,如果創(chuàng)建了代理或者說重寫了 InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation 方法并在方法 postProcessBeforeInstantiation 中改變了 bean赏酥,則直接返回就可以了甸箱,否則需要進行常規(guī) bean 的創(chuàng)建糯而。而這常規(guī) bean 的創(chuàng)建就是在 doCreateBean 中完成的账嚎。

AbstractAutowireCapableBeanFactory#doCreateBean

/**
 * Actually create the specified bean. Pre-creation processing has already happened
 * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
 * <p>Differentiates between default bean instantiation, use of a
 * factory method, and autowiring a constructor.
 * @param beanName the name of the bean
 * @param mbd the merged bean definition for the bean
 * @param args explicit arguments to use for constructor or factory method invocation
 * @return a new instance of the bean
 * @throws BeanCreationException if the bean could not be created
 * @see #instantiateBean
 * @see #instantiateUsingFactoryMethod
 * @see #autowireConstructor
 */
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
        throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) { // 1
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) { // 2
         // 根據(jù)指定 bean 使用對應(yīng)的策略創(chuàng)建新的實例涂身,如:工廠方法雄卷、構(gòu)造函數(shù)自動注入、簡單初始化
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    mbd.resolvedTargetType = beanType;

    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                  // 應(yīng)用 MergedBeanDefinitionPostProcessor
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); // 3
            }
            catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    // 4
    // 是否需要提前曝光:單例 & 允許循環(huán)依賴 & 當前 bean 正在創(chuàng)建中蛤售,檢測循環(huán)依賴
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
        if (logger.isDebugEnabled()) {
            logger.debug("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        // 為了避免后期循環(huán)依賴丁鹉,可以在 bean 初始化完成前將創(chuàng)建實例的 ObjectFactory 加入工廠
        addSingletonFactory(beanName, new ObjectFactory<Object>() {
            @Override
            public Object getObject() throws BeansException {
                // 對 bean 再一次依賴引用妒潭,主要應(yīng)用 SmartInstantiationAware BeanPostProcessor,
                // 其中我們熟知的 AOP 就是在這里將 advice 動態(tài)織入 bean 中,若沒有直接返回 bean揣钦,不做任何處理
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // 對 bean 進行填充雳灾,將各個屬性值注入,其中冯凹,可能存在依賴于其他 bean 的屬性谎亩,則會遞歸初始依賴 bean
       // 5
        populateBean(beanName, mbd, instanceWrapper);
        if (exposedObject != null) {
            // 調(diào)用初始化方法,比如 init-method
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }
        else {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }

    if (earlySingletonExposure) {
        Object earlySingletonReference = getSingleton(beanName, false);
        // earlySingletonReference 只有在檢測到有循環(huán)依賴的情況下才會不為空
        // 6
        if (earlySingletonReference != null) {
            // 如果 esposedObject 沒有在初始化方法中被改變宇姚,就是沒有被增強
            if (exposedObject == bean) {
                exposedObject = earlySingletonReference;
            }
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                      // 檢測依賴
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                // 因為 bean 創(chuàng)建后其所依賴的 bean 一定是已經(jīng)創(chuàng)建的匈庭,
                // actualDependentBeans 不為空則表示當前 bean 創(chuàng)建后其依賴的 bean 卻沒有
                // 全部創(chuàng)建完,也就是說存在循環(huán)依賴
                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName,
                            "Bean with name '" + beanName + "' has been injected into other beans [" +
                            StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                            "] in its raw version as part of a circular reference, but has eventually been " +
                            "wrapped. This means that said other beans do not use the final version of the " +
                            "bean. This is often the result of over-eager type matching - consider using " +
                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        // 根據(jù) scopes 注冊 bean
        registerDisposableBeanIfNecessary(beanName, bean, mbd); // 7
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }
  
    return exposedObject; // 8
}
  1. 如果是單例則需要首先清除緩存

  2. 實例化 bean浑劳,將 BeanDefinition 轉(zhuǎn)換為 BeanWrapper

    轉(zhuǎn)換是一個復(fù)雜的過程阱持,但是我們可以嘗試概括大致的功能:

    • 如果存在工廠方法則使用工廠方法進行初始化
    • 一個類有多個構(gòu)造函數(shù),每個構(gòu)造函數(shù)都有不同的參數(shù)魔熏,所以需要根據(jù)參數(shù)鎖定構(gòu)造函數(shù)并進行初始化
    • 如果既不存在工廠方法也不存在帶有參數(shù)的構(gòu)造函數(shù)衷咽,則使用默認的構(gòu)造函數(shù)進行 bean 的實例化
  3. MergedBeanDefinitionPostProcessor的應(yīng)用

    bean合并后的處理,Autowired注解正是通過此方法實現(xiàn)諸如類型的預(yù)解析蒜绽。

  4. 依賴處理

    在Spring中會有循環(huán)依賴的情況镶骗,例如,當A中含有B的屬性躲雅,而B中又含有A的屬性時就會構(gòu)成一個循環(huán)依賴卖词,此時如果A和B都是單例,那么在Spring中的處理方式就是當創(chuàng)建B的時候吏夯,涉及自動注入A的步驟時此蜈,并不是直接去再次創(chuàng)建A,而是通過放入緩存中的ObjectFactory來創(chuàng)建實例噪生,這樣就解決了循環(huán)依賴的問題裆赵。

  5. 屬性填充。將所有屬性填充至bean的實例中

  6. 循環(huán)依賴檢查

    Sping 中解決循環(huán)依賴只對單例有效跺嗽,而對于 prototype 的 bean战授,Spring 沒有好的解決辦法,唯一要做的就是拋出異常桨嫁。在這個步驟里面會檢測已經(jīng)加載的 bean 是否已經(jīng)出現(xiàn)了依賴循環(huán)植兰,并判斷是否需要拋出異常。

  7. 注冊DisposableBean

    如果配置了destroy-method璃吧,這里需要注冊以便于在銷毀時候調(diào)用楣导。

  8. 完成創(chuàng)建并返回

創(chuàng)建 bean 的實例 (createBeanInstance)

/**
 * Create a new instance for the specified bean, using an appropriate instantiation strategy:
 * factory method, constructor autowiring, or simple instantiation.
 * @param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @param args explicit arguments to use for constructor or factory method invocation
 * @return BeanWrapper for the new instance
 * @see #instantiateUsingFactoryMethod
 * @see #autowireConstructor
 * @see #instantiateBean
 */
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, 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());
    }

    // 如果工廠方法不為空則使用工廠方法初始化策略
    if (mbd.getFactoryMethodName() != null)  { // 1
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
  
    // 2
    // Shortcut when re-creating the same bean...
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            // 一個類有多個構(gòu)造函數(shù),每個構(gòu)造函數(shù)都有不同的參數(shù)畜挨,所以調(diào)用前需要先根據(jù)參數(shù)鎖定構(gòu)造函數(shù)或?qū)?yīng)的工廠方法
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    // 如果已經(jīng)解析過則使用解析好的構(gòu)造函數(shù)方法不需要再次鎖定
    if (resolved) {
        if (autowireNecessary) {
            // 構(gòu)造函數(shù)自動注入
            return autowireConstructor(beanName, mbd, null, null);
        }
        else {
            // 使用默認構(gòu)造函數(shù)構(gòu)造
            return instantiateBean(beanName, mbd);
        }
    }

    // Need to determine the constructor...
    // 需要根據(jù)參數(shù)解析構(gòu)造函數(shù)
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
         // 構(gòu)造函數(shù)自動注入
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // No special handling: simply use no-arg constructor.
    // 使用默認構(gòu)造函數(shù)構(gòu)造
    return instantiateBean(beanName, mbd);
}
  1. 如果在RootBeanDefinition中存在factoryMethodName屬性筒繁,或者說在配置文件中配置了factory-method噩凹,那么 Spring 會嘗試使用instantiateUsingFactoryMethod(beanName, mbd, args)方法根據(jù)RootBeanDefinition中的配置生成bean的實例。
  2. 解析構(gòu)造函數(shù)并進行構(gòu)造函數(shù)的實例化毡咏。因為一個 bean 對應(yīng)的類中可能會有多個構(gòu)造函數(shù)翩活,而每個構(gòu)造函數(shù)的參數(shù)不同蔓挖,Spring 在根據(jù)參數(shù)及類型去判斷最終會使用哪個構(gòu)造函數(shù)進行實例化贪壳。但是筒愚,判斷的過程是個比較消耗性能的步驟,所以采用緩存機制恢总,如果已經(jīng)解析過則不需要重復(fù)解析而是直接從RootBeanDefinition中的屬性resolvedConstructorOrFactoryMethod緩存的值去取落恼,否則需要再次解析,并將解析的結(jié)果添加至 RootBeanDefinition 中的屬性resolvedConstructorOrFactoryMethod中离熏。
### autowireConstructor

對于實例的創(chuàng)建Spring中分成了兩種情況,一種是通用的實例化戴涝,另一種是帶有參數(shù)的實例化滋戳。帶有參數(shù)的實例化過程相當復(fù)雜,因為存在著不確定性啥刻,所以在判斷對應(yīng)參數(shù)上做了大量工作奸鸯。

/**
 * "autowire constructor" (with constructor arguments by type) behavior.
 * Also applied if explicit constructor argument values are specified,
 * matching all remaining arguments with beans from the bean factory.
 * <p>This corresponds to constructor injection: In this mode, a Spring
 * bean factory is able to host components that expect constructor-based
 * dependency resolution.
 * @param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @param ctors the chosen candidate constructors
 * @param explicitArgs argument values passed in programmatically via the getBean method,
 * or {@code null} if none (-> use constructor argument values from bean definition)
 * @return BeanWrapper for the new instance
 */ 
 protected BeanWrapper autowireConstructor(
        String beanName, RootBeanDefinition mbd, Constructor<?>[] ctors, Object[] explicitArgs) {

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

這邊的代碼量太大了,不太適合貼出來解析可帽,各位最好還是去 idea 里面進行查看娄涩,書中作者也覺得這段不符合 Spring 那種『將復(fù)雜的邏輯分解,分成N個小函數(shù)的嵌套映跟,每一層都是對下一層邏輯的總結(jié)及概要蓄拣,這樣使得每一層的邏輯會變得簡單容易理解』的規(guī)律。我這里就說明一下整體流程努隙,每段流程貼出對應(yīng)的代碼球恤。

構(gòu)造函數(shù)參數(shù)的確定

  • 根據(jù)explicitArgs參數(shù)判斷

    如果傳入的參數(shù)explicitArgs不為空,那邊可以直接確定參數(shù)荸镊,因為 explicitArgs 參數(shù)是在調(diào)用 Bean 的時候用戶指定的咽斧,在BeanFactory類中存在這樣的方法:
    Object getBean(String name, Object... args) throws BeansException;
    在獲取 bean 的時候,用戶不但可以指定 bean 的名稱還可以指定 bean 所對應(yīng)類的構(gòu)造函數(shù)或者工廠方法的方法參數(shù)躬存,主要用于靜態(tài)工廠方法的調(diào)用张惹,而這里是需要給定完全匹配的參數(shù)的,所以岭洲,便可以判斷宛逗,如果傳入?yún)?shù)explicitArgs不為空,則可以確定構(gòu)造函數(shù)參數(shù)就是它盾剩。

    // explicitArgs 通過 getBean 方法傳入
    // 如果 getBean 方法調(diào)用的時候指定方法參數(shù)那么直接使用
    if (explicitArgs != null) {
     argsToUse = explicitArgs
    }
    
  • 緩存中獲取

    構(gòu)造函數(shù)參數(shù)已經(jīng)記錄在緩存中拧额,那么便可以直接拿來使用碑诉。而且,這里要提到的是侥锦,在緩存中緩存的可能是參數(shù)的最終類型也可能是參數(shù)的初始類型进栽,例如:構(gòu)造函數(shù)參數(shù)要求的是 int 類型,但是原始的參數(shù)值可能是String類型的“1”恭垦,那么即使在緩存中得到了參數(shù)快毛,也需要經(jīng)過類型轉(zhuǎn)換器的過濾以確保參數(shù)類型與對應(yīng)的構(gòu)造函數(shù)參數(shù)類型完全對應(yīng)。

    else {
              // 如果在 getBean 方法時候沒有指定則嘗試從配置文件中解析
     Object[] argsToResolve = null;
              // 嘗試從緩存中獲取
     synchronized (mbd.constructorArgumentLock) {
         constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
         if (constructorToUse != null && mbd.constructorArgumentsResolved) {
             // Found a cached constructor...
                       // 從緩存中取
             argsToUse = mbd.resolvedConstructorArguments;
             if (argsToUse == null) {
                           // 配置的構(gòu)造函數(shù)參數(shù) 
                 argsToResolve = mbd.preparedConstructorArguments;
             }
         }
     }
              // 如果緩存中存在
     if (argsToResolve != null) {
                  // 解析參數(shù)類型番挺,如給定方法的構(gòu)造函數(shù) A(int, int) 則通過此方法后就會把配置匯中的 ("1", "1") 轉(zhuǎn)換為 (1, 1)
                  // 緩存中的值可能是原始值也可能是最終值
         argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
     }
    }
    
  • 配置文件獲取

    如果不能根據(jù)傳入的參數(shù) explicitArgs 確定構(gòu)造函數(shù)的參數(shù)也無法在緩存中得到相關(guān)信息唠帝,那么只能開始新一輪的分析了。
    分析從獲取配置文件中配置的構(gòu)造函數(shù)信息開始玄柏,經(jīng)過之前的分析襟衰,我們知道,Spring中配置文件中的信息經(jīng)過轉(zhuǎn)換都會通過 BeanDefinition 實例承載粪摘,也就是參數(shù)mbd中包含瀑晒,那么可以通過調(diào)用 mbd.getConstructorArgumentValues()來獲取配置的構(gòu)造函數(shù)信息。有了配置中的信息便可以獲取對應(yīng)的參數(shù)值信息了徘意,獲取參數(shù)值的信息包括直接指定值苔悦,如:直接指定構(gòu)造函數(shù)中某個值為原始類型 String 類型,或者是一個對其他 bean 的引用椎咧,而這一處理委托給resolveConstructorArguments方法玖详,并返回能解析到的參數(shù)的個數(shù)。

    // Need to resolve the constructor.
    boolean autowiring = (chosenCtors != null ||
         mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR);
    ConstructorArgumentValues resolvedValues = null;
    
    int minNrOfArgs;
    if (explicitArgs != null) {
     minNrOfArgs = explicitArgs.length;
    }
    else {
              // 提取配置文件中的配置的構(gòu)造函數(shù)參數(shù)
     ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
              // 用于承載解析后的構(gòu)造函數(shù)參數(shù)的值
     resolvedValues = new ConstructorArgumentValues();
              // 能解析到的參數(shù)個數(shù)
     minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
    }
    

構(gòu)造函數(shù)的確認

經(jīng)過了第一步后已經(jīng)確定了構(gòu)造函數(shù)的參數(shù)勤讽,接下來的任務(wù)就是根據(jù)構(gòu)造函數(shù)參數(shù)在所有構(gòu)造函數(shù)中鎖定對應(yīng)的構(gòu)造函數(shù)蟋座,而匹配的方法就是根據(jù)參數(shù)個數(shù)匹配,所以在匹配之前需要先對構(gòu)造函數(shù)按照public構(gòu)造函數(shù)優(yōu)先參數(shù)數(shù)量降序脚牍、非public構(gòu)造函數(shù)參數(shù)數(shù)量降序蜈七。這樣可以在遍歷的情況下迅速判斷排在后面的構(gòu)造函數(shù)參數(shù)個數(shù)是否符合條件。

// Take specified constructors, if any.
Constructor<?>[] candidates = chosenCtors;
if (candidates == null) {
    Class<?> beanClass = mbd.getBeanClass();
    try {
        candidates = (mbd.isNonPublicAccessAllowed() ?
                beanClass.getDeclaredConstructors() : beanClass.getConstructors());
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Resolution of declared constructors on bean Class [" + beanClass.getName() +
                "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
    }
}
// 排序給定的構(gòu)造函數(shù)莫矗,public 構(gòu)造函數(shù)優(yōu)先參數(shù)數(shù)量排序飒硅、非 public 構(gòu)造函數(shù)參數(shù)數(shù)量降序
AutowireUtils.sortConstructors(candidates);

由于在配置文件中并不是唯一限制使用參數(shù)位置索引的方式去創(chuàng)建,同樣還支持指定參數(shù)名稱進行設(shè)定參數(shù)值的情況作谚,如<constructor-arg name="aa">三娩,那么這種情況就需要首先確定構(gòu)造函數(shù)中的參數(shù)名稱。

獲取參數(shù)名稱可以有兩種方式

  1. 通過注解的方式直接獲取妹懒,

    String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
    
  2. 使用Spring中提供的工具類 ParameterNameDiscoverer 來獲取雀监。構(gòu)造函數(shù)、參數(shù)名稱、參數(shù)類型会前、參數(shù)值都確定后就可以鎖定構(gòu)造函數(shù)以及轉(zhuǎn)換對應(yīng)的參數(shù)類型了好乐。

    if (paramNames == null) {
     ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
     if (pnd != null) {
         paramNames = pnd.getParameterNames(candidate);
     }
    }
    

根據(jù)確定的構(gòu)造函數(shù)轉(zhuǎn)換對應(yīng)的參數(shù)類型

主要是使用Spring中提供的類型轉(zhuǎn)換器或者用戶提供的自定義類型轉(zhuǎn)換器進行轉(zhuǎn)換。

argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
                                getUserDeclaredConstructor(candidate), autowiring);

構(gòu)造參數(shù)不確定性的驗證

當然瓦宜,有時候即使構(gòu)造函數(shù)蔚万、參數(shù)名稱、參數(shù)類型临庇、參數(shù)值都確定后也不一定會直接鎖定構(gòu)造函數(shù)反璃,不同構(gòu)造函數(shù)的參數(shù)為父子關(guān)系,所以Spring在最后又做了一次驗證假夺。

// 探測是否有不確定性的構(gòu)造函數(shù)存在淮蜈,例如不同構(gòu)造函數(shù)的參數(shù)為父子關(guān)系
int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
        argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
// Choose this constructor if it represents the closest match.
// 如果它代表著當前最接近的匹配則選擇作為構(gòu)造函數(shù)
if (typeDiffWeight < minTypeDiffWeight) {
    constructorToUse = candidate;
    argsHolderToUse = argsHolder;
    argsToUse = argsHolder.arguments;
    minTypeDiffWeight = typeDiffWeight;
    ambiguousConstructors = null;
}
else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
    if (ambiguousConstructors == null) {
        ambiguousConstructors = new LinkedHashSet<Constructor<?>>();
        ambiguousConstructors.add(constructorToUse);
    }
    ambiguousConstructors.add(candidate);
}

根據(jù)實例化策略以及得到的構(gòu)造函數(shù)及構(gòu)造函數(shù)參數(shù)實例化Bean

if (System.getSecurityManager() != null) {
    final Constructor<?> ctorToUse = constructorToUse;
    final Object[] argumentsToUse = argsToUse;
    beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
        @Override
        public Object run() {
            return beanFactory.getInstantiationStrategy().instantiate(
                    mbd, beanName, beanFactory, ctorToUse, argumentsToUse);
        }
    }, beanFactory.getAccessControlContext());
}
else {
    beanInstance = this.beanFactory.getInstantiationStrategy().instantiate(
            mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
}

后面章節(jié)進行描述。

instantiateBean 不帶參數(shù)的構(gòu)造函數(shù)實例化過程

if (resolved) {
    if (autowireNecessary) {
        return autowireConstructor(beanName, mbd, null, null);
    }
    else {
        return instantiateBean(beanName, mbd);
    }
}
/**
 * Instantiate the given bean using its default constructor.
 * @param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @return BeanWrapper for the new instance
 */
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
        Object beanInstance;
        final BeanFactory parent = this;
        if (System.getSecurityManager() != null) {
            beanInstance = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    return getInstantiationStrategy().instantiate(mbd, beanName, parent);
                }
            }, getAccessControlContext());
        }
        else {
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
        }
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        initBeanWrapper(bw);
        return bw;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
}

實例化策略

其實已卷,經(jīng)過前面的分析梧田,我們已經(jīng)得到了足以實例化的所有相關(guān)信息,完全可以使用最簡單的反射方法直接反射來構(gòu)造實例對象侧蘸,但是Spring卻并沒有這么做裁眯。

SimpleInstantiationStrategy#instantiate

@Override
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
    // Don't override the class with CGLIB if no overrides.
     // 如果有需要覆蓋或者動態(tài)替換的方法則當然需要使用 cglib 進行動態(tài)代理,因為可以在
     // 創(chuàng)建代理的同時將方法將動態(tài)方法織入類中闺魏,但是如果沒有需要動態(tài)改變的方法,為了
     // 方便直接反射就可以了
    if (bd.getMethodOverrides().isEmpty()) {
        Constructor<?> constructorToUse;
        synchronized (bd.constructorArgumentLock) {
            constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
            if (constructorToUse == null) {
                final Class<?> clazz = bd.getBeanClass();
                if (clazz.isInterface()) {
                    throw new BeanInstantiationException(clazz, "Specified class is an interface");
                }
                try {
                    if (System.getSecurityManager() != null) {
                        constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
                            @Override
                            public Constructor<?> run() throws Exception {
                                return clazz.getDeclaredConstructor((Class[]) null);
                            }
                        });
                    }
                    else {
                        constructorToUse =  clazz.getDeclaredConstructor((Class[]) null);
                    }
                    bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                }
                catch (Throwable ex) {
                    throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                }
            }
        }
        return BeanUtils.instantiateClass(constructorToUse);
    }
    else {
        // Must generate CGLIB subclass.
        return instantiateWithMethodInjection(bd, beanName, owner);
    }
}

CglibSubclassingInstantiationStrategy#instantiate

/**
 * An inner class created for historical reasons to avoid external CGLIB dependency
 * in Spring versions earlier than 3.2.
 */
private static class CglibSubclassCreator {

    private static final Class<?>[] CALLBACK_TYPES = new Class<?>[]
            {NoOp.class, LookupOverrideMethodInterceptor.class, ReplaceOverrideMethodInterceptor.class};

    private final RootBeanDefinition beanDefinition;

    private final BeanFactory owner;

    CglibSubclassCreator(RootBeanDefinition beanDefinition, BeanFactory owner) {
        this.beanDefinition = beanDefinition;
        this.owner = owner;
    }

    /**
     * Create a new instance of a dynamically generated subclass implementing the
     * required lookups.
     * @param ctor constructor to use. If this is {@code null}, use the
     * no-arg constructor (no parameterization, or Setter Injection)
     * @param args arguments to use for the constructor.
     * Ignored if the {@code ctor} parameter is {@code null}.
     * @return new instance of the dynamically generated subclass
     */
    public Object instantiate(Constructor<?> ctor, Object... args) {
        Class<?> subclass = createEnhancedSubclass(this.beanDefinition);
        Object instance;
        if (ctor == null) {
            instance = BeanUtils.instantiateClass(subclass);
        }
        else {
            try {
                Constructor<?> enhancedSubclassConstructor = subclass.getConstructor(ctor.getParameterTypes());
                instance = enhancedSubclassConstructor.newInstance(args);
            }
            catch (Exception ex) {
                throw new BeanInstantiationException(this.beanDefinition.getBeanClass(),
                        "Failed to invoke constructor for CGLIB enhanced subclass [" + subclass.getName() + "]", ex);
            }
        }
        // SPR-10785: set callbacks directly on the instance instead of in the
        // enhanced class (via the Enhancer) in order to avoid memory leaks.
        Factory factory = (Factory) instance;
        factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
                new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
                new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
        return instance;
    }

    /**
     * Create an enhanced subclass of the bean class for the provided bean
     * definition, using CGLIB.
     */
    private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(beanDefinition.getBeanClass());
        enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
        if (this.owner instanceof ConfigurableBeanFactory) {
            ClassLoader cl = ((ConfigurableBeanFactory) this.owner).getBeanClassLoader();
            enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(cl));
        }
        enhancer.setCallbackFilter(new MethodOverrideCallbackFilter(beanDefinition));
        enhancer.setCallbackTypes(CALLBACK_TYPES);
        return enhancer.createClass();
    }
}

記錄創(chuàng)建 bean 的 ObjectFactory

doCreate 函數(shù)中有這樣一段代碼:

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 4
// 是否需要提前曝光:單例 & 允許循環(huán)依賴 & 當前 bean 正在創(chuàng)建中俯画,檢測循環(huán)依賴
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
        isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
    if (logger.isDebugEnabled()) {
        logger.debug("Eagerly caching bean '" + beanName +
                "' to allow for resolving potential circular references");
    }
    // 為了避免后期循環(huán)依賴析桥,可以在 bean 初始化完成前將創(chuàng)建實例的 ObjectFactory 加入工廠
    addSingletonFactory(beanName, new ObjectFactory<Object>() {
        @Override
        public Object getObject() throws BeansException {
            // 對 bean 再一次依賴引用,主要應(yīng)用 SmartInstantiationAware BeanPostProcessor,
            // 其中我們熟知的 AOP 就是在這里將 advice 動態(tài)織入 bean 中艰垂,若沒有直接返回 bean泡仗,不做任何處理
            return getEarlyBeanReference(beanName, mbd, bean);
        }
    });
}
  • mbd.isSingleton: 是否是單例
  • this.allowCircularReferences: 是否允許循環(huán)依賴,很抱歉猜憎,并沒有找到在配置文件中如何配置娩怎,但是在 AbstractRefreshableApplicationContext 中提供了設(shè)置函數(shù),可以通過硬編碼的方式進行設(shè)置或者可以通過自定義命名空間進行配置胰柑,其中硬編碼的方式代碼如下:

    ClassPathXmlApplicationContext bf = new ClassPathXmlApplicationContext ("aspectTest.xml");
    bf.setAllowBeanDefinitionOverriding(false);
    
  • isSingletonCurrentlyInCreation(beanName): 該bean是否在創(chuàng)建中截亦。在Spring中,會有個專門的屬性默認為DefaultSingletonBeanRegistrysingletonsCurrentlyInCreation來記錄bean的加載狀態(tài)柬讨,在bean開始創(chuàng)建前會將beanName記錄在屬性中崩瓤,在bean創(chuàng)建結(jié)束后會將 beanName 從屬性中移除。

    記錄狀態(tài)的點踩官,不同 scope 的位置不一樣却桶,以 singleton 為例,在singleton下記錄屬性的函數(shù)是在DefaultSingletonBeanRegistry類的 public Object getSingleton(String beanName, ObjectFactory singletonFacotry) 函數(shù)的 beforeSingletonCreation(beanName)afterSingletonCreation(beanName) 中,在這兩段函數(shù)中分別是 this.singletonsCurrentlyInCreation.add(beanName)this.singletonsCurrentlyInCreation.remove(beanName) 來進行狀態(tài)的記錄與移除颖系。

屬性注入

// Initialize the bean instance.
Object exposedObject = bean;
try {
    populateBean(beanName, mbd, instanceWrapper);
    if (exposedObject != null) {
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
}
/**
 * Populate the bean instance in the given BeanWrapper with the property values
 * from the bean definition.
 * @param beanName the name of the bean
 * @param mbd the bean definition for the bean
 * @param bw BeanWrapper with bean instance
 */
protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
    PropertyValues pvs = mbd.getPropertyValues();

    if (bw == null) {
        if (!pvs.isEmpty()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        else {
            // Skip property population phase for null instance.
             // 沒有可填充的屬性
            return;
        }
    }

    // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
    // state of the bean before properties are set. This can be used, for example,
    // to support styles of field injection.
     // 給 InstantiationAwareBeanPostprocessors 最優(yōu)一次機會在屬性設(shè)置前來改變 bean
     // 如:可以用來支持屬性注入的類型
    boolean continueWithPropertyPopulation = true;

    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) { // 1
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                  // 返回值為是否繼續(xù)填充 bean
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    continueWithPropertyPopulation = false;
                    break;
                }
            }
        }
    }
    // 如果后處理器發(fā)出停止填充命令則終止后續(xù)的運行
    if (!continueWithPropertyPopulation) {
        return;
    }

     // 2
    if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
            mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

        // Add property values based on autowire by name if applicable.
         // 根據(jù)名稱自動注入
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }

        // Add property values based on autowire by type if applicable.
         // 根據(jù)類型自動注入
        if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }

        pvs = newPvs;
    }

     // 后處理器已經(jīng)初始化
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
     // 需要依賴檢查
    boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

    if (hasInstAwareBpps || needsDepCheck) {
        PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        if (hasInstAwareBpps) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) { // 3
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                      // 對所有需要依賴檢查的屬性進行后處理
                    pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvs == null) {
                        return;
                    }
                }
            }
        }
        if (needsDepCheck) {
             // 依賴檢查嗅剖,對應(yīng) depends-on 屬性, 3.0 已經(jīng)棄用此屬性
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
    }
 
     // 將屬性應(yīng)用到 bean 中
    applyPropertyValues(beanName, mbd, bw, pvs); // 4
}
  1. InstantiationAwareBeanPostProcessor處理器的postProcessAfterInstantiation函數(shù)的應(yīng)用嘁扼,此函數(shù)可以控制程序是否繼續(xù)進行屬性填充信粮。
  2. 根據(jù)注入類型(byName/byType),提取依賴的 bean偷拔,并統(tǒng)一存入PropertyValues中蒋院。
  3. 應(yīng)用InstantiationAwareBeanPostProcessor處理器的postProcessPropertyValues方法,對屬性獲取完畢填充前對屬性的再次處理莲绰,典型應(yīng)用是 RequiredAnnotationBeanPostProcessor 類中對屬性的驗證欺旧。
  4. 將所有PropertyValues中的屬性填充至BeanWrapper中。

在上面的步驟中有幾個地方是我們比較感興趣的蛤签,它們分別是依賴注入( autowireByName/autowireByType)以及屬性填充辞友,那么,接下來進一步分析這幾個功能的實現(xiàn)細節(jié)震肮。

autowireByName

protected void autowireByName(
        String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

     // 尋找 bw 中需要依賴注入的屬性
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        if (containsBean(propertyName)) {
             // 遞歸初始化相關(guān)的 bean 
            Object bean = getBean(propertyName);
            pvs.add(propertyName, bean);
             // 注冊依賴
            registerDependentBean(propertyName, beanName);
            if (logger.isDebugEnabled()) {
                logger.debug("Added autowiring by name from bean name '" + beanName +
                        "' via property '" + propertyName + "' to bean named '" + propertyName + "'");
            }
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
                        "' by name: no matching bean found");
            }
        }
    }
}

autowireByType

protected void autowireByType(
        String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }

    Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
     // 尋找 bw 中需要依賴注入的屬性
    String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
    for (String propertyName : propertyNames) {
        try {
            PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
            // Don't try autowiring by type for type Object: never makes sense,
            // even if it technically is a unsatisfied, non-simple property.
            if (Object.class != pd.getPropertyType()) {
                  // 探測指定屬性的 set 方法
                MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
                // Do not allow eager init for type matching in case of a prioritized post-processor.
                boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
                DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
                Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
                  // 解析指定 beanName 的屬性所匹配的值称龙,并把解析到的屬性名稱存儲在 
                  // autowireBeanNames 中,當屬性存在多個封裝 bean 時戳晌,如:
                  // @Autowired private List<A> aList; 將會找到所有匹配 A 類型
                  // 的 bean 并將其注入
                if (autowiredArgument != null) {
                    pvs.add(propertyName, autowiredArgument);
                }
                for (String autowiredBeanName : autowiredBeanNames) {
                      // 注冊依賴
                    registerDependentBean(autowiredBeanName, beanName);
                    if (logger.isDebugEnabled()) {
                        logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
                                propertyName + "' to bean named '" + autowiredBeanName + "'");
                    }
                }
                autowiredBeanNames.clear();
            }
        }
        catch (BeansException ex) {
            throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
        }
    }
}

現(xiàn)根據(jù)名稱自動匹配的第一步就是尋找 bw 中需要依賴注入的屬性鲫尊,同樣對于根據(jù)類型自動匹配的實現(xiàn)來講第一步也是尋找bw中需要依賴注入的屬性,然后遍歷這些屬性并尋找類型匹配的 bean沦偎,其中最復(fù)雜的就是尋找類型匹配的 bean疫向。

DefaultListableBeanFactory#resolveDependency

public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
        Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

    descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
    if (javaUtilOptionalClass == descriptor.getDependencyType()) {
        return new OptionalDependencyFactory().createOptionalDependency(descriptor, requestingBeanName);
    }
    else if (ObjectFactory.class == descriptor.getDependencyType() ||
            ObjectProvider.class == descriptor.getDependencyType()) {
         // ObjectFactory 類注入的特殊處理
        return new DependencyObjectProvider(descriptor, requestingBeanName);
    }
    else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
         // javaxInjectProviderClass 類注入的特殊處理
        return new Jsr330ProviderFactory().createDependencyProvider(descriptor, requestingBeanName);
    }
    else {
        Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
                descriptor, requestingBeanName);
        if (result == null) {
              // 通用邏輯處理
            result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
        }
        return result;
    }
}
public Object doResolveDependency(DependencyDescriptor descriptor, String beanName,
        Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException {

    InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
    try {
        Object shortcut = descriptor.resolveShortcut(this);
        if (shortcut != null) {
            return shortcut;
        }

        Class<?> type = descriptor.getDependencyType();
         // 用于支持 Spring 中的注解 @Value
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
        if (value != null) {
            if (value instanceof String) {
                String strVal = resolveEmbeddedValue((String) value);
                BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null);
                value = evaluateBeanDefinitionString(strVal, bd);
            }
            TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
            return (descriptor.getField() != null ?
                    converter.convertIfNecessary(value, type, descriptor.getField()) :
                    converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
        }

        Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
        if (multipleBeans != null) {
            return multipleBeans;
        }

         // 根據(jù)屬性類型找到 beanFactory 中所有類型的匹配 bean,
         // 返回值的構(gòu)成為: key: 匹配的 beanName, value: beanName 對應(yīng)的實例化后的 bean(通過 getBean(beanName) 返回)
        Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
        if (matchingBeans.isEmpty()) {
              // 如果 autowire 的 require 屬性為 true 而找到的匹配項卻為空則只能拋出異常
            if (descriptor.isRequired()) {
                raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
            }
            return null;
        }

        String autowiredBeanName;
        Object instanceCandidate;

        if (matchingBeans.size() > 1) {
            autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
            if (autowiredBeanName == null) {
                if (descriptor.isRequired() || !indicatesMultipleBeans(type)) {
                    return descriptor.resolveNotUnique(type, matchingBeans);
                }
                else {
                    // In case of an optional Collection/Map, silently ignore a non-unique case:
                    // possibly it was meant to be an empty collection of multiple regular beans
                    // (before 4.3 in particular when we didn't even look for collection beans).
                    return null;
                }
            }
            instanceCandidate = matchingBeans.get(autowiredBeanName);
        }
        else {
            // We have exactly one match.
            Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
            autowiredBeanName = entry.getKey();
            instanceCandidate = entry.getValue();
        }

        if (autowiredBeanNames != null) {
            autowiredBeanNames.add(autowiredBeanName);
        }
        return (instanceCandidate instanceof Class ?
                descriptor.resolveCandidate(autowiredBeanName, type, this) : instanceCandidate);
    }
    finally {
        ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
    }
}

applyPropertyValues

程序運行到這里豪嚎,已經(jīng)完成了對所有注入屬性的獲取搔驼,但是獲取的屬性是以PropertyValues形式存在的,還并沒有應(yīng)用到已經(jīng)實例化的bean中侈询,這一工作是在applyPropertyValues中舌涨。

/**
 * Apply the given property values, resolving any runtime references
 * to other beans in this bean factory. Must use deep copy, so we
 * don't permanently modify this property.
 * @param beanName the bean name passed for better exception information
 * @param mbd the merged bean definition
 * @param bw the BeanWrapper wrapping the target object
 * @param pvs the new property values
 */
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
    if (pvs == null || pvs.isEmpty()) {
        return;
    }

    MutablePropertyValues mpvs = null;
    List<PropertyValue> original;

    if (System.getSecurityManager() != null) {
        if (bw instanceof BeanWrapperImpl) {
            ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
        }
    }

    if (pvs instanceof MutablePropertyValues) {
        mpvs = (MutablePropertyValues) pvs;
         // 如果 mpvs 中的值已經(jīng)被轉(zhuǎn)換為對應(yīng)的類型那么可以直接設(shè)置到 beanWapper 中
        if (mpvs.isConverted()) {
            // Shortcut: use the pre-converted values as-is.
            try {
                bw.setPropertyValues(mpvs);
                return;
            }
            catch (BeansException ex) {
                throw new BeanCreationException(
                        mbd.getResourceDescription(), beanName, "Error setting property values", ex);
            }
        }
        original = mpvs.getPropertyValueList();
    }
    else {
         // 如果 pvs 并不是使用 MutablePropertyValues 封裝的類型,那么直接使用原始的屬性獲取方法
        original = Arrays.asList(pvs.getPropertyValues());
    }

    TypeConverter converter = getCustomTypeConverter();
    if (converter == null) {
        converter = bw;
    }
     // 獲取對應(yīng)的解析器
    BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

    // Create a deep copy, resolving any references for values.
    List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
    boolean resolveNecessary = false;
     // 遍歷屬性扔字,將屬性轉(zhuǎn)換為對應(yīng)類的對應(yīng)屬性的類型
    for (PropertyValue pv : original) {
        if (pv.isConverted()) {
            deepCopy.add(pv);
        }
        else {
            String propertyName = pv.getName();
            Object originalValue = pv.getValue();
            Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
            Object convertedValue = resolvedValue;
            boolean convertible = bw.isWritableProperty(propertyName) &&
                    !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
            if (convertible) {
                convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
            }
            // Possibly store converted value in merged bean definition,
            // in order to avoid re-conversion for every created bean instance.
            if (resolvedValue == originalValue) {
                if (convertible) {
                    pv.setConvertedValue(convertedValue);
                }
                deepCopy.add(pv);
            }
            else if (convertible && originalValue instanceof TypedStringValue &&
                    !((TypedStringValue) originalValue).isDynamic() &&
                    !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
                pv.setConvertedValue(convertedValue);
                deepCopy.add(pv);
            }
            else {
                resolveNecessary = true;
                deepCopy.add(new PropertyValue(pv, convertedValue));
            }
        }
    }
    if (mpvs != null && !resolveNecessary) {
        mpvs.setConverted();
    }

    // Set our (possibly massaged) deep copy.
    try {
        bw.setPropertyValues(new MutablePropertyValues(deepCopy));
    }
    catch (BeansException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Error setting property values", ex);
    }
}

初始化 bean

大家應(yīng)該記得在 bean 配置時 bean 中有一個init-method的屬性囊嘉,這個屬性的作用是在 bean 實例化前調(diào)用init-method指定的方法來根據(jù)用戶業(yè)務(wù)進行相應(yīng)的實例化。我們現(xiàn)在就已經(jīng)進入這個方法了革为,首先看一下這個方法的執(zhí)行位置哗伯,Spring中程序已經(jīng)執(zhí)行過bean的實例化,并且進行了屬性的填充篷角,而就在這時將會調(diào)用用戶設(shè)定的初始化方法焊刹。

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            @Override
            public Object run() {
                invokeAwareMethods(beanName, bean);
                return null;
            }
        }, getAccessControlContext());
    }
    else {
         // 對特殊的 bean 處理:Aware、BeanClassLoaderAware、BeanFactoryAware
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
         // 應(yīng)用后處理器
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
         // 激活用戶自定義的 init 方法
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                (mbd != null ? mbd.getResourceDescription() : null),
                beanName, "Invocation of init method failed", ex);
    }

    if (mbd == null || !mbd.isSynthetic()) {
         // 后處理器應(yīng)用
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

激活 Aware 方法

Spring 中提供一些 Aware 相關(guān)接口虐块,比如 BeanFactoryAware俩滥、ApplicationContextAwareResourceLoaderAware贺奠、ServletContextAware 等霜旧,實現(xiàn)這些 Aware 接口的 bean 在被初始之后,可以取得一些相對應(yīng)的資源儡率,例如實現(xiàn)BeanFactoryAware 的 bean 在初始后挂据, Spring 容器將會注入 BeanFactory 的實例,而實現(xiàn)ApplicationContextAware的bean儿普,在bean被初始后崎逃,將會被注入ApplicationContext的實例等。

Aware 的使用

  1. 定義 bean

    public class Hello {
        public void say() {
            System.out.println("hello");
        }
    }
    
  2. 定義 BeanFactoryAware 類型的 bean

    public class TestAware implements BeanFactoryAware {
        private BeanFactory beanFactory;
    
        // 聲明 bean 的時候 Spring 會自動注入 BeanFactory
        @Override
        public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
            this.beanFactory = beanFactory;
        }
    
        public void testAware() {
            // 通過 hello 這個 bean id 從 beanFactory 獲取實例
            Hello hello = (Hello) beanFactory.getBean("hello");
            hello.say();
        }
    }
    
  3. 測試

    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("testAware.xml");
        TestAware testAware = (TestAware) ctx.getBean("testAware");
        testAware.testAware();
    }
    
    /**
    hello
    **/
    

invokeAwareMethods

private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
        }
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

處理器的應(yīng)用

BeanPostProcessor相信大家都不陌生眉孩,這是 Spring 中開放式架構(gòu)中一個必不可少的亮點个绍,給用戶充足的權(quán)限去更改或者擴展 Spring ,而除了 BeanPostProcessor 外還有很多其他的 PostProcessor浪汪,當然大部分都是以此為基礎(chǔ)巴柿,繼承自 BeanPostProcessorBeanPostProcessor 的使用位置就是這里死遭,在調(diào)用客戶自定義初始化方法前以及調(diào)用自定義初始化方法后分別會調(diào)用 BeanPostProcessorpostProcessBeforeInitializationpostProcessAfterInitialization方法广恢,使用戶可以根據(jù)自己的業(yè)務(wù)需求進行響應(yīng)的處理。

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        result = beanProcessor.postProcessBeforeInitialization(result, beanName);
        if (result == null) {
            return result;
        }
    }
    return result;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
        throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
        result = beanProcessor.postProcessAfterInitialization(result, beanName);
        if (result == null) {
            return result;
        }
    }
    return result;
}

激活自定義的 init 方法

客戶定制的初始化方法除了我們熟知的使用配置init-method外呀潭,還有使自定義的 bean 實現(xiàn)InitializingBean接口钉迷,并在afterPropertiesSet中實現(xiàn)自己的初始化業(yè)務(wù)邏輯。

init-methodafterPropertiesSet都是在初始化 bean 時執(zhí)行蜗侈,執(zhí)行順序是afterPropertiesSet先執(zhí)行篷牌,而init-method后執(zhí)行睡蟋。

invokeInitMethods方法中就實現(xiàn)了這兩個步驟的初始化方法調(diào)用踏幻。

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
        throws Throwable {
    // 首先會檢查是否是 InitializingBean,如果是的話需要調(diào)用 afterPropertiesSet 方法
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                    @Override
                    public Object run() throws Exception {
                        ((InitializingBean) bean).afterPropertiesSet();
                        return null;
                    }
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
              // 屬性初始化后的處理
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }

    if (mbd != null) {
        String initMethodName = mbd.getInitMethodName();
        if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
              // 調(diào)用自定義初始化方法
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

注冊 DisposableBean

Spring 中不但提供了對于初始化方法的擴展入口戳杀,同樣也提供了銷毀方法的擴展入口该面,對于銷毀方法的擴展,除了我們熟知的配置屬性destroy-method方法外信卡,用戶還可以注冊后處理器DestructionAwareBeanPostProcessor來統(tǒng)一處理bean的銷毀方法隔缀,代碼如下(doCreateBean中):

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
    AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
    if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
        if (mbd.isSingleton()) {
            // Register a DisposableBean implementation that performs all destruction
            // work for the given bean: DestructionAwareBeanPostProcessors,
            // DisposableBean interface, custom destroy method.
              // 單例模式下注冊需要銷毀的 bean,此方法中會處理實現(xiàn) DisposableBean 的 bean傍菇,
              // 并且堆所有的 bean 使用 DestructionAwareBeanPostProcessors 處理
              // DisposableBean DestructionAwareBeanPostProcessors
            registerDisposableBean(beanName,
                    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
        }
        else {
            // A bean with a custom scope...
              // 自定義 scope 的處理
            Scope scope = this.scopes.get(mbd.getScope());
            if (scope == null) {
                throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
            }
            scope.registerDestructionCallback(beanName,
                    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
        }
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末猾瘸,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌牵触,老刑警劉巖淮悼,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異揽思,居然都是意外死亡袜腥,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門钉汗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來羹令,“玉大人,你說我怎么就攤上這事损痰「3蓿” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵徐钠,是天一觀的道長癌刽。 經(jīng)常有香客問我,道長尝丐,這世上最難降的妖魔是什么显拜? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮爹袁,結(jié)果婚禮上远荠,老公的妹妹穿的比我還像新娘。我一直安慰自己失息,他們只是感情好譬淳,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盹兢,像睡著了一般邻梆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绎秒,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天浦妄,我揣著相機與錄音,去河邊找鬼见芹。 笑死剂娄,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的玄呛。 我是一名探鬼主播阅懦,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼徘铝!你這毒婦竟也來了耳胎?” 一聲冷哼從身側(cè)響起惯吕,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎怕午,沒想到半個月后混埠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡诗轻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年钳宪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扳炬。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡吏颖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出恨樟,到底是詐尸還是另有隱情半醉,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布劝术,位于F島的核電站缩多,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏养晋。R本人自食惡果不足惜衬吆,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绳泉。 院中可真熱鬧逊抡,春花似錦、人聲如沸零酪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽四苇。三九已至孝凌,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間月腋,已是汗流浹背蟀架。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留罗售,地道東北人辜窑。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓钩述,卻偏偏與公主長得像寨躁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子牙勘,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容