Spring-IOC-循環(huán)依賴檢測與Bean的創(chuàng)建

Spring容器的循環(huán)依賴檢測

Spring容器循環(huán)依賴包括:構(gòu)造器循環(huán)依賴和setter循環(huán)依賴掺喻。

1- 構(gòu)造器循環(huán)依賴

通過構(gòu)造器注入構(gòu)成的循環(huán)依賴,此依賴是無法解決的,只能拋出BeanCurrentlyInCreationException異常表示循環(huán)依賴

描述:創(chuàng)建A類是,構(gòu)造器需要B類,那將去創(chuàng)建B空凸,在創(chuàng)建B時又發(fā)現(xiàn)需要C類,則又去創(chuàng)建C類寸痢,最終在創(chuàng)建C時發(fā)現(xiàn)又需要A呀洲,從而形成一個環(huán),沒辦法創(chuàng)建啼止。

原理:Spring容器將每一個正在創(chuàng)建的bean標識符放在一個“當前創(chuàng)建bean池”中道逗,bean標識符創(chuàng)建過程中將一直保持在這個池中,因為如果在創(chuàng)建bean過程中發(fā)現(xiàn)自己已經(jīng)在“當前創(chuàng)建bean池”中時献烦,將會拋出BeanCurrentlyInCreationException異常表示循環(huán)依賴滓窍;而對于創(chuàng)建完畢的bean將從“當前創(chuàng)建bean池”中清除掉。

過程分析(構(gòu)造器依賴 A -> B -> C -> A):

  1. Spring容器創(chuàng)建A bean巩那,首先去 “當前創(chuàng)建bean池”中查找是否當前bean正在創(chuàng)建(通過beanName)吏夯,如果發(fā)現(xiàn)沒有,則繼續(xù)準備其需要的構(gòu)造器參數(shù)B即横,并將A標識符放到“當前創(chuàng)建bean池”
  2. Spring容器創(chuàng)建B bean噪生,Spring容器創(chuàng)建B bean,首先去 “當前創(chuàng)建bean池”中查找是否當前bean正在創(chuàng)建(通過beanName)东囚,如果發(fā)現(xiàn)沒有跺嗽,則繼續(xù)準備其需要的構(gòu)造器參數(shù)C,并將B標識符放到“當前創(chuàng)建bean池”
  3. Spring容器創(chuàng)建C bean页藻,Spring容器創(chuàng)建C bean桨嫁,首先去 “當前創(chuàng)建bean池”中查找是否當前bean正在創(chuàng)建(通過beanName),如果發(fā)現(xiàn)沒有份帐,則繼續(xù)準備其需要的構(gòu)造器參數(shù)A璃吧,并將C標識符放到“當前創(chuàng)建bean池”
  4. C的創(chuàng)建需要先創(chuàng)建A bean,此時發(fā)現(xiàn)A已經(jīng)在“當前創(chuàng)建bean池”中弥鹦,檢測到了循環(huán)依賴肚逸,直接拋出BeanCurrentlyInCreationException異常
2- setter循環(huán)依賴

通過setter注入方式構(gòu)成的循環(huán)依賴爷辙。

原理:對于setter注入造成的依賴是通過Spring容器提前暴露剛完成構(gòu)造器注入但未完成其他步驟(比如setter注入)的bean來完成的彬坏,而且只能解決單例作用域的bean循環(huán)依賴。

通過提前暴露一個單例工廠方法膝晾,從而使其他bean能引用到該bean addSingletonFactory()方法

步驟(setter依賴關(guān)系 A -> B -> C -> A)

  1. Spring容器創(chuàng)建單例A的bean栓始,首先根據(jù)無參構(gòu)造器創(chuàng)建bean,并暴露一個“ObjectFactory”用于返回一個提前暴露一個創(chuàng)建中的bean血当,并將A標識符放到“當前創(chuàng)建bean池”幻赚,然后進行setter注入 B bean

  2. Spring容器創(chuàng)建單例B bean禀忆,首先根據(jù)無參構(gòu)造器創(chuàng)建bean,并暴露一個“ObjectFactory”用于返回一個提前暴露一個創(chuàng)建中的bean落恼,并將B標識符放到“當前創(chuàng)建bean池”箩退,然后進行setter注入 C bean

  3. Spring容器創(chuàng)建單例C bean,首先根據(jù)無參構(gòu)造器創(chuàng)建bean佳谦,并暴露一個“ObjectFactory”用于返回一個提前暴露一個創(chuàng)建中的bean戴涝,并將C標識符放到“當前創(chuàng)建bean池”,然后進行setter注入 A bean钻蔑,在進行注入A bean 時由于提前暴露了“ObjectFactory”工廠啥刻,從而使用它返回提前暴露一個創(chuàng)建中的bean

  4. 最后從3中循環(huán)結(jié)束,依次返回完成對 B bean咪笑、A bean的setter注入

3- prototype范圍的依賴處理
  1. 對于scope為prototype范圍的bean可帽,Spring容器無法完成依賴注入,因為Spring容器不進行緩存“prototype”作用域的bean窗怒,因此無法提前暴露一個創(chuàng)建中的bean映跟,所以檢測到循環(huán)依賴會直接拋出BeanCurrentlyInCreationException異常

  2. 對于單例作用域的bean,可以通過“setAllowCircularReferences(false)”來禁用循環(huán)引用扬虚,這樣如果存在循環(huán)引用就會拋出異常來通知用戶申窘。

doCreateBean方法

程序有兩個選擇:

  1. 如果創(chuàng)建了代理或者重寫了InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法并在方法postPorcessBeforeInstantiation中改變了bean,則直接返回就可以了孔轴。
  2. 否則需要進行常規(guī)bean的創(chuàng)建剃法,常規(guī)創(chuàng)建就是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) {
        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                mbd.postProcessed = true;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        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");
            }
            addSingletonFactory(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                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);
            if (earlySingletonReference != null) {
                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);
                        }
                    }
                    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 {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

主要步驟:

  1. 如果是單例則需要首先清除緩存

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

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

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

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

  4. 依賴處理:用 ObjectFactory來解決單例的setter循環(huán)依賴的問題

  5. 屬性填充劳澄,將所有屬性填充至bean的實例中

  6. 循環(huán)依賴檢查,對于已加載的bean,檢測是否已經(jīng)出現(xiàn)了循環(huán)依賴双吆,并判斷是否需要拋出異常好乐。

  7. 注冊DisposableBean:如果配置了destroy-method,這里需要注冊以便在銷毀時調(diào)用

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

下面主要講解步驟2,4,5,6,7

步驟2- 實例化bean
  1. 如果在RootBeanDefinition中存在factoryMethodName屬性曹宴,或者說在配置文件中配置了factory-method歉提,nameSpring會嘗試使用instantiateUsingFactoryMethod()方法根據(jù)RootBeanDefinition中的配置生成bean的實例区转。
  2. 解析構(gòu)造函數(shù)并進行構(gòu)造函數(shù)的實例化。因為一個bean對應的類中可能會有多個構(gòu)造函數(shù)版扩,而每一個構(gòu)造函數(shù)參數(shù)不同礁芦,需要Spring去解析姑躲,為了提高性能司草,每次解析的結(jié)果都緩存下來艰垂,存放在RootBeanDefinition中的屬性ResolvedConstructorOrFactoryMethod中,當下次判斷時直接從緩存中查找埋虹,如果沒有解析則會去解析猜憎。

實例的創(chuàng)建分為兩種:通用的實例化、帶有參數(shù)的實例化

    /**
     * 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<?> 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)  {
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }

        // Shortcut when re-creating the same bean...
        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {
            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);
            }
        }

        // Need to determine the constructor...
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null ||
                mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
            return autowireConstructor(beanName, mbd, ctors, args);
        }

        // No special handling: simply use no-arg constructor.
        return instantiateBean(beanName, mbd);
    }

1- 帶有參數(shù)的實例化

相當復雜搔课,因為存在不確定性胰柑,所以在判斷對應參數(shù)上做了大量工作。

autowireConstructor方法詳解

1. 帶有參數(shù)的bean的實例化
beans.factory.support.ConstructorResolver
    /**
     * "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 merged bean definition for the bean
     * @param chosenCtors chosen candidate constructors (or {@code null} if none)
     * @param explicitArgs argument values passed in programmatically via the getBean method,
     * or {@code null} if none (-> use constructor argument values from bean definition)
     * @return a BeanWrapper for the new instance
     */
    public BeanWrapper autowireConstructor(final String beanName, final RootBeanDefinition mbd,
            Constructor<?>[] chosenCtors, final Object[] explicitArgs) {

        BeanWrapperImpl bw = new BeanWrapperImpl();
        this.beanFactory.initBeanWrapper(bw);

        Constructor<?> constructorToUse = null;
        ArgumentsHolder argsHolderToUse = null;
        Object[] argsToUse = null;

        if (explicitArgs != null) {
            argsToUse = explicitArgs;
        }
        else {
            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) {
                        argsToResolve = mbd.preparedConstructorArguments;
                    }
                }
            }
            if (argsToResolve != null) {
                argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
            }
        }

        if (constructorToUse == null) {
            // 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 {
                ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
                resolvedValues = new ConstructorArgumentValues();
                minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
            }

            // 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);
                }
            }
            AutowireUtils.sortConstructors(candidates);
            int minTypeDiffWeight = Integer.MAX_VALUE;
            Set<Constructor<?>> ambiguousConstructors = null;
            LinkedList<UnsatisfiedDependencyException> causes = null;

            for (Constructor<?> candidate : candidates) {
                Class<?>[] paramTypes = candidate.getParameterTypes();

                if (constructorToUse != null && argsToUse.length > paramTypes.length) {
                    // Already found greedy constructor that can be satisfied ->
                    // do not look any further, there are only less greedy constructors left.
                    break;
                }
                if (paramTypes.length < minNrOfArgs) {
                    continue;
                }

                ArgumentsHolder argsHolder;
                if (resolvedValues != null) {
                    try {
                        String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, paramTypes.length);
                        if (paramNames == null) {
                            ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
                            if (pnd != null) {
                                paramNames = pnd.getParameterNames(candidate);
                            }
                        }
                        argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
                                getUserDeclaredConstructor(candidate), autowiring);
                    }
                    catch (UnsatisfiedDependencyException ex) {
                        if (this.beanFactory.logger.isTraceEnabled()) {
                            this.beanFactory.logger.trace(
                                    "Ignoring constructor [" + candidate + "] of bean '" + beanName + "': " + ex);
                        }
                        // Swallow and try next constructor.
                        if (causes == null) {
                            causes = new LinkedList<UnsatisfiedDependencyException>();
                        }
                        causes.add(ex);
                        continue;
                    }
                }
                else {
                    // Explicit arguments given -> arguments length must match exactly.
                    if (paramTypes.length != explicitArgs.length) {
                        continue;
                    }
                    argsHolder = new ArgumentsHolder(explicitArgs);
                }

                int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
                        argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
                // Choose this constructor if it represents the closest match.
                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);
                }
            }

            if (constructorToUse == null) {
                if (causes != null) {
                    UnsatisfiedDependencyException ex = causes.removeLast();
                    for (Exception cause : causes) {
                        this.beanFactory.onSuppressedException(cause);
                    }
                    throw ex;
                }
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Could not resolve matching constructor " +
                        "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
            }
            else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Ambiguous constructor matches found in bean '" + beanName + "' " +
                        "(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
                        ambiguousConstructors);
            }

            if (explicitArgs == null) {
                argsHolderToUse.storeCache(mbd, constructorToUse);
            }
        }

        try {
            Object beanInstance;

            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);
            }

            bw.setBeanInstance(beanInstance);
            return bw;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean instantiation via constructor failed", ex);
        }
    }

步驟

  1. 構(gòu)造函數(shù)參數(shù)的確定
  1. 根據(jù)explicitArgs參數(shù)判斷
    在獲取bean的時候(調(diào)用getBean()方法)爬泥,用戶不但可以指定bean的名稱還可以指定bean所對應類的構(gòu)造函數(shù)或者工廠方法的方法參數(shù)旦事,主要用于靜態(tài)工廠方法的調(diào)用,而這里是需要給定完全匹配的參數(shù)的急灭,因此explicitArgs不為空姐浮,則可以確定對應的構(gòu)造函數(shù)
  2. 緩存中獲取解析過的方法匹配
    構(gòu)造函數(shù)參數(shù)已經(jīng)記錄在緩存中,則可以直接拿來使用葬馋,但是需要注意的是緩存中的參數(shù)可能是參數(shù)的最終類型也可能是參數(shù)的初始類型卖鲤,如String類型的“1”表示的int類型數(shù)據(jù),此時需要經(jīng)過類型轉(zhuǎn)換器的過濾來確保參數(shù)類型與對應的構(gòu)造函數(shù)參數(shù)類型完全對應畴嘶。
  3. 配置文件讀取
    即不能從1蛋逾、2中獲取到信息來確定構(gòu)造函數(shù)的參數(shù),則從bean配置加載轉(zhuǎn)化為BeanDefinition實例的getConstructorArgumentValues()來獲取配置的構(gòu)造函數(shù)信息
  1. 構(gòu)造函數(shù)的確定

根據(jù)1中確定的參數(shù)鎖定對應的構(gòu)造函數(shù)窗悯,匹配的方法就是根據(jù)參數(shù)個數(shù)匹配区匣,所以在匹配之前需要對構(gòu)造器的可見性以及參數(shù)數(shù)量進行排序,之后就能快速判定是哪個構(gòu)造函數(shù)了蒋院,對于沒有限制參數(shù)位置索引的方式而是指定參數(shù)名稱進行參數(shù)設(shè)定的情況亏钩,就需要首先確定構(gòu)造函數(shù)中的參數(shù)名稱莲绰。獲取參數(shù)名稱可以通過注解的方式直接獲取,一種是使用工具類ParameterNameDiscoverer來獲取

  1. 根據(jù)確定的構(gòu)造函數(shù)轉(zhuǎn)換對應的參數(shù)類型姑丑,主要是使用Spring中提供的類型轉(zhuǎn)換器或者用戶提供的自定義類型轉(zhuǎn)換器進行轉(zhuǎn)換

  2. 構(gòu)造函數(shù)不確定性的驗證蛤签,對不同構(gòu)造函數(shù)的參數(shù)類型的父子關(guān)系,進行最后一次驗證栅哀,這個步驟之后才能真正的鎖定一個構(gòu)造函數(shù)

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

2- 通用不帶參數(shù)的實例化

2. 不帶參數(shù)實例化
beans.factory.support.AbstractAutowireCapableBeanFactory
    /**
     * 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);
        }
    }

instantiateBean方法完成不帶參數(shù)的實例化震肮,邏輯比較簡單,直接調(diào)用實例化策略進行實例化留拾,接下來介紹實例化策略戳晌。

3- 實例化策略

3 實例化策略
beans.factory.support.SimpleInstantiationStrategy

    @Override
    public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
        // Don't override the class with CGLIB if no overrides.
        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);
        }
    }
beans.factory.support.CglibSubclassingInstantiationStrategy(繼承自SimpleInstantiationStrategy)
內(nèi)部靜態(tài)類
    ClassLoaderAwareGeneratorStrategy (extends DefaultGeneratorStrategy)
        /**
         * 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;
        }
  1. 首先判斷如果BeanDefinition.getMethodOverrides()為空也就是用戶沒有使用replace或者lookup的配置方法,則直接使用反射調(diào)用構(gòu)造器構(gòu)造對象實例
  2. 如果設(shè)置了上述兩個特性痴柔,則必須使用動態(tài)代理的方式將包含兩個特性所對應的邏輯的攔截器增強器設(shè)置進去躬厌,這樣才可以保證在調(diào)用方法的時候會被相應的攔截器增強,返回值為包含攔截器的代理實例
步驟4- 創(chuàng)建bean的ObjectFactory竞帽,用以解決循環(huán)依賴的問題

重點看一下ObjectFactory的實現(xiàn)

可以總結(jié)出來Spring解決循環(huán)依賴的方法:

在B中創(chuàng)建依賴A時通過ObjectFactory提供的實例化方法來中斷A中的屬性填充扛施,使B中持有的A僅僅是剛剛初始化并沒有填充任何屬性的A,而這正初始化A的步驟還是在最開始創(chuàng)建A的時候進行的屹篓,但是因為A與B中的A所表示的屬性地址是一樣的疙渣,所以在A中創(chuàng)建好的屬性填充自然可以通過B中的A獲取,這樣就解決了循環(huán)依賴的問題堆巧。

記錄創(chuàng)建bean的ObjectFactory
beans.factory.support.AbstractAutowireCapableBeanFactory
    /**
     * Obtain a reference for early access to the specified bean,
     * typically for the purpose of resolving a circular reference.
     * @param beanName the name of the bean (for error handling purposes)
     * @param mbd the merged bean definition for the bean
     * @param bean the raw bean instance
     * @return the object to expose as bean reference
     */
    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
        Object exposedObject = bean;
        if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                    SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                    exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
                    if (exposedObject == null) {
                        return null;
                    }
                }
            }
        }
        return exposedObject;
    }
步驟5- 屬性注入
 屬性注入

    /**
     * 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.
        boolean continueWithPropertyPopulation = true;

        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (BeanPostProcessor bp : getBeanPostProcessors()) {
                if (bp instanceof InstantiationAwareBeanPostProcessor) {
                    InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }

        if (!continueWithPropertyPopulation) {
            return;
        }

        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.
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }

            // Add property values based on autowire by type if applicable.
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }

            pvs = newPvs;
        }

        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) {
                        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                        pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvs == null) {
                            return;
                        }
                    }
                }
            }
            if (needsDepCheck) {
                checkDependencies(beanName, mbd, filteredPds, pvs);
            }
        }

        applyPropertyValues(beanName, mbd, bw, pvs);
    }

populatedBean方法的調(diào)用邏輯:

  1. InstantiationAwareBeanPostProcessor處理器的postProcessAfterInstantiation函數(shù)的應用妄荔,此函數(shù)可以控制是否繼續(xù)進行填充
  2. 根據(jù)注入類型(byName、byType)谍肤,提取依賴的bean啦租,并統(tǒng)一存入PropertyValues中
  3. 應用InstantiationAwareBeanPostProcessor處理器的postProcessPropertyValues方法,對屬性獲取完畢填充前對屬性的再次處理荒揣,典型應用是RequiredAnnotationBeanPostProcessor類中對屬性的驗證篷角。
  4. 將所有PropertyValues中的屬性填充至BeanWrapper中。

下面主要分析屬性依賴注入填充:

1- autowireByName

原理:在傳入的參數(shù)pvs中找到已經(jīng)加載的bean系任,并遞歸實例化恳蹲,進而加入到pvs中

1 autowireByName
    /**
     * Fill in any missing property values with references to
     * other beans in this factory if autowire is set to "byName".
     * @param beanName the name of the bean we're wiring up.
     * Useful for debugging messages; not used functionally.
     * @param mbd bean definition to update through autowiring
     * @param bw BeanWrapper from which we can obtain information about the bean
     * @param pvs the PropertyValues to register wired objects with
     */
    protected void autowireByName(
            String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

        String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
        for (String propertyName : propertyNames) {
            if (containsBean(propertyName)) {
                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");
                }
            }
        }
    }

2- autowireByType
相比于1最復雜的在于尋找bw中需要依賴注入的屬性,然后遍歷這些屬性并尋找類型匹配的bean俩滥,其中最復雜的就是尋找類型匹配的bean嘉蕾,同時,Spring中提供了對集合的類型注入的支持霜旧,如

@Autowired
        private List<AType> ATypes;

這會將所有AType匹配的類型找出來并注入到Atypes集合中错忱,正是因為這一因素,autowireByType函數(shù)中新建了autowiredBeanNames,用于存儲所有依賴的bean以清。
尋找類型匹配的邏輯實現(xiàn)封裝在了resolveDependency函數(shù)中

2 autowireByType
    /**
     * Abstract method defining "autowire by type" (bean properties by type) behavior.
     * <p>This is like PicoContainer default, in which there must be exactly one bean
     * of the property type in the bean factory. This makes bean factories simple to
     * configure for small namespaces, but doesn't work as well as standard Spring
     * behavior for bigger applications.
     * @param beanName the name of the bean to autowire by type
     * @param mbd the merged bean definition to update through autowiring
     * @param bw BeanWrapper from which we can obtain information about the bean
     * @param pvs the PropertyValues to register wired objects with
     */
    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);
        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()) {
                    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);
                    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);
            }
        }
    }
2.1 尋找類型匹配
beans.factory.support.DefaultListableBeanFactory
    @Override
    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()) {
            return new DependencyObjectProvider(descriptor, requestingBeanName);
        }
        else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
            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();
            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;
            }

            Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
            if (matchingBeans.isEmpty()) {
                if (isRequired(descriptor)) {
                    raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
                }
                return null;
            }

            String autowiredBeanName;
            Object instanceCandidate;

            if (matchingBeans.size() > 1) {
                autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
                if (autowiredBeanName == null) {
                    if (isRequired(descriptor) || !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);
        }
    }

3- 將獲取的屬性應用到實例化bean中
1儿普、2完成了屬性的獲取,并以PropertyValues形式存在的玖媚。

3 應用獲取的屬性到實例化bean上
beans.factory.support.AbstractAutowireCapableBeanFactory
    /**
     * 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;
            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 {
            original = Arrays.asList(pvs.getPropertyValues());
        }

        TypeConverter converter = getCustomTypeConverter();
        if (converter == null) {
            converter = bw;
        }
        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;
        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);
        }
    }
步驟6- 初始化bean

Spring中已經(jīng)執(zhí)行過bean的實例化箕肃,并且進行了屬性的填充婚脱,而就在這時會調(diào)用用戶配置的初始化方法(init-method子元素)除了調(diào)用用戶自定義的初始化方法還做了一些必要的工作今魔。

1- 激活Aware方法
Spring中提供了一些Aware相關(guān)接口,比如BeanFactoryAware障贸、ApplicationContextAware错森、ResourceLoaderAware、ServletContextAware等篮洁,實現(xiàn)了這些Aware接口的bean在被初始化后涩维,Spring容器將會注入BeanFactory的實例,而實現(xiàn)ApplicationContextAware的bean袁波,在bean被初始化后瓦阐,將會被注入ApplicationContext的實例等

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);
            }
        }
    }

2- 處理器的應用
處理器給用戶充足的權(quán)限去更改或者拓展Spring

    @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;
    }

3- 激活自定義的init方法
有兩種自定義初始化方法:自定義實現(xiàn)了InitializingBean接口,并在afterPropertiesSet中實現(xiàn)自己的初始化業(yè)務(wù)邏輯篷牌;在配置中設(shè)置init-method睡蟋。
執(zhí)行順序是先執(zhí)行afterPropertiesSet然后在執(zhí)行init-method方法

    /**
     * Give a bean a chance to react now all its properties are set,
     * and a chance to know about its owning bean factory (this object).
     * This means checking whether the bean implements InitializingBean or defines
     * a custom init method, and invoking the necessary callback(s) if it does.
     * @param beanName the bean name in the factory (for debugging purposes)
     * @param bean the new bean instance we may need to initialize
     * @param mbd the merged bean definition that the bean was created with
     * (can also be {@code null}, if given an existing bean instance)
     * @throws Throwable if thrown by init methods or by the invocation process
     * @see #invokeCustomInitMethod
     */
    protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
            throws Throwable {

        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)) {
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }
步驟7- 注冊DisposableBean

Spring提供了銷毀方法的拓展入口,Spring提供了兩種方式:配置屬性destroy-method枷颊;實現(xiàn)DisposableBean接口的destory方法執(zhí)行順序是先執(zhí)行destroy方法戳杀,然后在執(zhí)行destroy-method配置的方法

beans.factory.support.AbstractBeanFactory
    /**
     * Add the given bean to the list of disposable beans in this factory,
     * registering its DisposableBean interface and/or the given destroy method
     * to be called on factory shutdown (if applicable). Only applies to singletons.
     * @param beanName the name of the bean
     * @param bean the bean instance
     * @param mbd the bean definition for the bean
     * @see RootBeanDefinition#isSingleton
     * @see RootBeanDefinition#getDependsOn
     * @see #registerDisposableBean
     * @see #registerDependentBean
     */
    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.
                registerDisposableBean(beanName,
                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
            }
            else {
                // A bean with a custom 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閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件傍菇,死亡現(xiàn)場離奇詭異,居然都是意外死亡界赔,警方通過查閱死者的電腦和手機桥嗤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來仔蝌,“玉大人泛领,你說我怎么就攤上這事×簿” “怎么了渊鞋?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我锡宋,道長儡湾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任执俩,我火速辦了婚禮徐钠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘役首。我一直安慰自己尝丐,他們只是感情好,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布衡奥。 她就那樣靜靜地躺著爹袁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪矮固。 梳的紋絲不亂的頭發(fā)上失息,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天,我揣著相機與錄音档址,去河邊找鬼盹兢。 笑死,一個胖子當著我的面吹牛守伸,可吹牛的內(nèi)容都是我干的绎秒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼含友,長吁一口氣:“原來是場噩夢啊……” “哼替裆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起窘问,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤辆童,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后惠赫,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體把鉴,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年儿咱,在試婚紗的時候發(fā)現(xiàn)自己被綠了庭砍。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡混埠,死狀恐怖怠缸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情钳宪,我是刑警寧澤揭北,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布扳炬,位于F島的核電站,受9級特大地震影響搔体,放射性物質(zhì)發(fā)生泄漏恨樟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一疚俱、第九天 我趴在偏房一處隱蔽的房頂上張望劝术。 院中可真熱鬧,春花似錦呆奕、人聲如沸养晋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽匙握。三九已至咆槽,卻和暖如春陈轿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背秦忿。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工麦射, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人灯谣。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓潜秋,卻偏偏與公主長得像,于是被迫代替她去往敵國和親胎许。 傳聞我的和親對象是個殘疾皇子峻呛,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

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