Spring DI原理


DI

DI(Dependency Injection)依賴注入:就是指對象是被動接受依賴類而不是自己主動去找,換句話說就是指對象不是從容器中查找它依賴的類,而是在容器實例化對象的時候主動將它依賴的類注入給它。

依賴注入發生的時間

當 Spring IOC 容器完成了 Bean 定義資源的定位、載入和解析注冊以后,IOC 容器中已經管理類 Bean定義的相關數據,但是此時 IOC 容器還沒有對所管理的 Bean 進行依賴注入,依賴注入在以下兩種情況發生:
1)、用戶第一次調用 getBean()方法時,IOC 容器觸發依賴注入。
2)、當用戶在配置文件中將<bean>元素配置了 lazy-init=false 屬性,即讓容器在解析注冊 Bean 定義時進行預實例化,觸發依賴注入。

BeanFactory 接口定義了 Spring IOC 容器的基本功能規范,是 Spring IOC 容器所應遵守的最底層和最基本的編程規范。BeanFactory 接口中定義了幾個 getBean()方法,就是用戶向 IOC 容器索取管理的Bean 的方法,我們通過分析其子類AbstractBeanFactory 的具體實現,理解 Spring IOC 容器在用戶索取 Bean 時如何完成依賴注入。

AbstractBeanFactory 的 getBean()相關方法的源碼如下:

//獲取IOC容器中指定名稱的Bean
    @Override
    public Object getBean(String name) throws BeansException {
        //doGetBean才是真正向IoC容器獲取被管理Bean的過程
        return doGetBean(name, null, null, false);
    }

    //獲取IOC容器中指定名稱和類型的Bean
    @Override
    public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
        //doGetBean才是真正向IoC容器獲取被管理Bean的過程
        return doGetBean(name, requiredType, null, false);
    }

    //獲取IOC容器中指定名稱和參數的Bean
    @Override
    public Object getBean(String name, Object... args) throws BeansException {
        //doGetBean才是真正向IoC容器獲取被管理Bean的過程
        return doGetBean(name, null, args, false);
    }

    //獲取IOC容器中指定名稱、類型和參數的Bean
    public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
            throws BeansException {
        //doGetBean才是真正向IoC容器獲取被管理Bean的過程
        return doGetBean(name, requiredType, args, false);
    }

    @SuppressWarnings("unchecked")
    //真正實現向IOC容器獲取Bean的功能,也是觸發依賴注入功能的地方
    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

        //根據指定的名稱獲取被管理Bean的名稱,剝離指定名稱中對容器的相關依賴
        //如果指定的是別名,將別名轉換為規范的Bean名稱
        final String beanName = transformedBeanName(name);
        Object bean;

        // Eagerly check singleton cache for manually registered singletons.
        //先從緩存中取是否已經有被創建過的單態類型的Bean
        //對於單例模式的Bean整個IOC容器中只創建一次,不需要重復創建
        Object sharedInstance = getSingleton(beanName);
        //IOC容器創建單例模式Bean實例對象
        if (sharedInstance != null && args == null) {
            if (logger.isDebugEnabled()) {
                //如果指定名稱的Bean在容器中已有單例模式的Bean被創建
                //直接返回已經創建的Bean
                if (isSingletonCurrentlyInCreation(beanName)) {
                    logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
                }
                else {
                    logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }
            //獲取給定Bean的實例對象,主要是完成FactoryBean的相關處理
            //注意:BeanFactory是管理容器中Bean的工廠,而FactoryBean是
            //創建創建對象的工廠Bean,兩者之間有區別
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }

        else {
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            //緩存沒有正在創建的單例模式Bean
            //緩存中已經有已經創建的原型模式Bean
            //但是由於循環引用的問題導致實例化對象失敗
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            //對IOC容器中是否存在指定名稱的BeanDefinition進行檢查,首先檢查是否
            //能在當前的BeanFactory中獲取的所需要的Bean,如果不能則委托當前容器
            //的父級容器去查找,如果還是找不到則沿着容器的繼承體系向父級容器查找
            BeanFactory parentBeanFactory = getParentBeanFactory();
            //當前容器的父級容器存在,且當前容器中不存在指定名稱的Bean
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                //解析指定Bean名稱的原始名稱
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                }
                else if (args != null) {
                    // Delegation to parent with explicit args.
                    //委派父級容器根據指定名稱和顯式的參數查找
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    // No args -> delegate to standard getBean method.
                    //委派父級容器根據指定名稱和類型查找
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            //創建的Bean是否需要進行類型驗證,一般不需要
            if (!typeCheckOnly) {
                //向容器標記指定的Bean已經被創建
                markBeanAsCreated(beanName);
            }

            try {
                //根據指定Bean名稱獲取其父級的Bean定義
                //主要解決Bean繼承時子類合並父類公共屬性問題
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                //獲取當前Bean所有依賴Bean的名稱
                String[] dependsOn = mbd.getDependsOn();
                //如果當前Bean有依賴Bean
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        //遞歸調用getBean方法,獲取當前Bean的依賴Bean
                        registerDependentBean(dep, beanName);
                        //把被依賴Bean注冊給當前依賴的Bean
                        getBean(dep);
                    }
                }

                // Create bean instance.
                //創建單例模式Bean的實例對象
                if (mbd.isSingleton()) {
                    //這里使用了一個匿名內部類,創建Bean實例對象,並且注冊給所依賴的對象
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            //創建一個指定Bean實例對象,如果有父級繼承,則合並子類和父類的定義
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            //顯式地從容器單例模式Bean緩存中清除實例對象
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    //獲取給定Bean的實例對象
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                //IOC容器創建原型模式Bean實例對象
                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    //原型模式(Prototype)是每次都會創建一個新的對象
                    Object prototypeInstance = null;
                    try {
                        //回調beforePrototypeCreation方法,默認的功能是注冊當前創建的原型對象
                        beforePrototypeCreation(beanName);
                        //創建指定Bean對象實例
                        prototypeInstance = createBean(beanName, mbd, args);
                    }
                    finally {
                        //回調afterPrototypeCreation方法,默認的功能告訴IOC容器指定Bean的原型對象不再創建
                        afterPrototypeCreation(beanName);
                    }
                    //獲取給定Bean的實例對象
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                }

                //要創建的Bean既不是單例模式,也不是原型模式,則根據Bean定義資源中
                //配置的生命周期范圍,選擇實例化Bean的合適方法,這種在Web應用程序中
                //比較常用,如:request、session、application等生命周期
                else {
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    //Bean定義資源中沒有配置生命周期范圍,則Bean定義不合法
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }
                    try {
                        //這里又使用了一個匿名內部類,獲取一個指定生命周期范圍的實例
                        Object scopedInstance = scope.get(beanName, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        //獲取給定Bean的實例對象
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    }
                    catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
                    }
                }
            }
            catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }

        // Check if required type matches the type of the actual bean instance.
        //對創建的Bean實例對象進行類型檢查
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            }
            catch (TypeMismatchException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }

 通過上面對向 IOC 容器獲取 Bean 方法的分析,我們可以看到在 Spring 中,如果 Bean 定義的單例模式(Singleton),則容器在創建之前先從緩存中查找,以確保整個容器中只存在一個實例對象。如果 Bean定義的是原型模式(Prototype),則容器每次都會創建一個新的實例對象。除此之外,Bean 定義還可以通過指定的生命周期范圍來創建。

上面的源碼只是定義了根據 Bean 定義的模式,采取的不同創建 Bean 實例對象的策略,具體的 Bean實例 對象的創 建過程 由實現了AbstractBeanFactory接口 的匿名內 部類的createBean()方法 完成,AbstractBeanFactory使 用 委 派 模 式 , 具 體 的 Bean 實 例 創 建 過 程 交 由 其 實 現 類AbstractAutowireCapableBeanFactory 完成,我們繼續分析AbstractAutowireCapableBeanFactory的 createBean()方法的源碼,理解其創建 Bean 實例的具體實現過程。

開始實例化

AbstractAutowireCapableBeanFactory 類實現了 AbstractBeanFactory接口,創建容器指定的 Bean 實例對象,同時還對創建的 Bean 實例對象進行初始化處理。其創建 Bean 實例對象的方法源碼如下:

//創建Bean實例對象
    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        if (logger.isDebugEnabled()) {
            logger.debug("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;

        // Make sure bean class is actually resolved at this point, and
        // clone the bean definition in case of a dynamically resolved Class
        // which cannot be stored in the shared merged bean definition.
        //判斷需要創建的Bean是否可以實例化,即是否可以通過當前的類加載器加載
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // Prepare method overrides.
        //校驗和准備Bean中的方法覆蓋
        try {
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            //如果Bean配置了初始化前和初始化后的處理器,則試圖返回一個需要創建Bean的代理對象
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

        try {
            //創建Bean的入口
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isDebugEnabled()) {
                logger.debug("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException ex) {
            // A previously detected exception with proper bean creation context already...
            throw ex;
        }
        catch (ImplicitlyAppearedSingletonException ex) {
            // An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }

    //真正創建Bean的方法
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        //封裝被創建的Bean對象
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = instanceWrapper.getWrappedInstance();
        //獲取實例化對象的類型
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // Allow post-processors to modify the merged bean definition.
        //調用PostProcessor后置處理器
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                }
                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.
        //向容器中緩存單例模式的Bean對象,以防循環引用
        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, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Initialize the bean instance.
        //Bean對象的初始化,依賴注入在此觸發
        //這個exposedObject在初始化完成之后返回作為依賴注入完成后的Bean
        Object exposedObject = bean;
        try {
            //將Bean實例對象封裝,並且Bean定義中配置的屬性值賦值給實例對象
            populateBean(beanName, mbd, instanceWrapper);
            //初始化Bean對象
            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) {
            //獲取指定名稱的已注冊的單例模式Bean對象
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                //根據名稱獲取的已注冊的Bean和正在實例化的Bean是同一個
                if (exposedObject == bean) {
                    //當前實例化的Bean初始化完成
                    exposedObject = earlySingletonReference;
                }
                //當前Bean依賴其他Bean,並且當發生循環引用時不允許新創建實例對象
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                    //獲取當前Bean所依賴的其他Bean
                    for (String dependentBean : dependentBeans) {
                        //對依賴Bean進行類型檢查
                        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.
        //注冊完成依賴注入的Bean
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
        }

        return exposedObject;
    }

通過上面的源碼注釋,我們看到具體的依賴注入實現其實就在以下兩個方法中:
1)、createBeanInstance()方法,生成 Bean 所包含的 java 對象實例。
2)、populateBean()方法,對 Bean 屬性的依賴注入進行處理。
下面繼續分析這兩個方法的代碼實現。

選擇 Bean 實例化策略

在 createBeanInstance()方法中,根據指定的初始化策略,使用簡單工廠、工廠方法或者容器的自動裝配特性生成 Java 實例對象,創建對象的源碼如下:

//創建Bean的實例對象
    protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // Make sure bean class is actually resolved at this point.
        //檢查確認Bean是可實例化的
        Class<?> beanClass = resolveBeanClass(mbd, beanName);

        //使用工廠方法對Bean進行實例化
        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        }

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

        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) {
                //配置了自動裝配屬性,使用容器的自動裝配實例化
                //容器的自動裝配是根據參數類型匹配Bean的構造方法
                return autowireConstructor(beanName, mbd, null, null);
            }
            else {
                //使用默認的無參構造方法實例化
                return instantiateBean(beanName, mbd);
            }
        }

        // Need to determine the constructor...
        //使用Bean的構造方法進行實例化
        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);
    }
//使用默認的無參構造方法實例化Bean對象 protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) { try { Object beanInstance; final BeanFactory parent = this; //獲取系統的安全管理接口,JDK標准的安全管理API if (System.getSecurityManager() != null) { //這里是一個匿名內置類,根據實例化策略創建實例對象 beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> 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); } }

經過對上面的代碼分析,我們可以看出,對使用工廠方法和自動裝配特性的 Bean 的實例化相當比較清楚,調用相應的工廠方法或者參數匹配的構造方法即可完成實例化對象的工作,但是對於我們最常使用的默認無參構造方法就需要使用相應的初始化策略(JDK 的反射機制或者 CGLib)來進行初始化了,在方法 getInstantiationStrategy().instantiate()中就具體實現類使用初始策略實例化對象。

執行 Bean 實例化

在使用默認的無參構造方法創建 Bean 的實例化對象時,方法 getInstantiationStrategy().instantiate()調用了 SimpleInstantiationStrategy 類中的實例化 Bean 的方法,其源碼如下:

//使用初始化策略實例化Bean對象
    @Override
    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
        // Don't override the class with CGLIB if no overrides.
        //如果Bean定義中沒有方法覆蓋,則就不需要CGLIB父類類的方法
        if (!bd.hasMethodOverrides()) {
            Constructor<?> constructorToUse;
            synchronized (bd.constructorArgumentLock) {
                //獲取對象的構造方法或工廠方法
                constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
                //如果沒有構造方法且沒有工廠方法
                if (constructorToUse == null) {
                    //使用JDK的反射機制,判斷要實例化的Bean是否是接口
                    final Class<?> clazz = bd.getBeanClass();
                    if (clazz.isInterface()) {
                        throw new BeanInstantiationException(clazz, "Specified class is an interface");
                    }
                    try {
                        if (System.getSecurityManager() != null) {
                            //這里是一個匿名內置類,使用反射機制獲取Bean的構造方法
                            constructorToUse = AccessController.doPrivileged(
                                    (PrivilegedExceptionAction<Constructor<?>>) () -> clazz.getDeclaredConstructor());
                        }
                        else {
                            constructorToUse =    clazz.getDeclaredConstructor();
                        }
                        bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                    }
                    catch (Throwable ex) {
                        throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                    }
                }
            }
            //使用BeanUtils實例化,通過反射機制調用”構造方法.newInstance(arg)”來進行實例化
            return BeanUtils.instantiateClass(constructorToUse);
        }
        else {
            // Must generate CGLIB subclass.
            //使用CGLIB來實例化對象
            return instantiateWithMethodInjection(bd, beanName, owner);
        }
    }

通過上面的代碼分析,我們看到了如果 Bean 有方法被覆蓋了,則使用 JDK 的反射機制進行實例化,否則,使用 CGLib 進行實例化。instantiateWithMethodInjection() 方 法 調 用SimpleInstantiationStrategy 的 子 類CGLibSubclassingInstantiationStrategy 使用 CGLib 來進行初始化,其源碼如下:

//使用CGLIB進行Bean對象實例化
        public Object instantiate(@Nullable Constructor<?> ctor, @Nullable 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;
        }

        private Class<?> createEnhancedSubclass(RootBeanDefinition beanDefinition) {
            //CGLIB中的類
            Enhancer enhancer = new Enhancer();
            //將Bean本身作為其基類
            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);
            //使用CGLIB的createClass方法生成實例對象
            return enhancer.createClass();
        }
    }

CGLib 是一個常用的字節碼生成器的類庫,它提供了一系列 API 實現 Java 字節碼的生成和轉換功能。JDK 的動態代理只能針對接口,如果一個類沒有實現任何接口,要對其進行動態代理只能使用 CGLib。

准備依賴注入

在前面的分析中我們已經了解到 Bean 的依賴注入主要分為兩個步驟,首先調用 createBeanInstance()方法生成 Bean 所包含的 Java 對象實例。然后,調用 populateBean()方法,對 Bean 屬性的依賴注入進行處理。
上面我們已經分析了容器初始化生成 Bean 所包含的 Java 實例對象的過程,現在我們繼續分析生成對象后,Spring IOC 容器是如何將 Bean 的屬性依賴關系注入 Bean 實例對象中並設置好的,回到AbstractAutowireCapableBeanFactory 的 populateBean()方法,對屬性依賴注入的代碼如下:

//將Bean屬性設置到生成的實例對象上
    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        if (bw == null) {
            if (mbd.hasPropertyValues()) {
                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;
        }
        //獲取容器在解析Bean定義資源時為BeanDefiniton中設置的屬性值
        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

        //對依賴注入處理,首先處理autowiring自動裝配的依賴注入
        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.
            //根據Bean名稱進行autowiring自動裝配處理
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
                autowireByName(beanName, mbd, bw, newPvs);
            }

            // Add property values based on autowire by type if applicable.
            //根據Bean類型進行autowiring自動裝配處理
            if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
                autowireByType(beanName, mbd, bw, newPvs);
            }

            pvs = newPvs;
        }

        //對非autowiring的屬性進行依賴注入處理

        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);

        if (hasInstAwareBpps || needsDepCheck) {
            if (pvs == null) {
                pvs = mbd.getPropertyValues();
            }
            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);
            }
        }

        if (pvs != null) {
            //對屬性進行注入
            applyPropertyValues(beanName, mbd, bw, pvs);
        }
    }

//解析並注入依賴屬性的過程
    protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
        if (pvs.isEmpty()) {
            return;
        }

        //封裝屬性值
        MutablePropertyValues mpvs = null;
        List<PropertyValue> original;

        if (System.getSecurityManager() != null) {
            if (bw instanceof BeanWrapperImpl) {
                //設置安全上下文,JDK安全機制
                ((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;
        }
        //創建一個Bean定義屬性值解析器,將Bean定義中的屬性值解析為Bean實例對象的實際值
        BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);

        // Create a deep copy, resolving any references for values.

        //為屬性的解析值創建一個拷貝,將拷貝的數據注入到實例對象中
        List<PropertyValue> deepCopy = new ArrayList<>(original.size());
        boolean resolveNecessary = false;
        for (PropertyValue pv : original) {
            //屬性值不需要轉換
            if (pv.isConverted()) {
                deepCopy.add(pv);
            }
            //屬性值需要轉換
            else {
                String propertyName = pv.getName();
                //原始的屬性值,即轉換之前的屬性值
                Object originalValue = pv.getValue();
                //轉換屬性值,例如將引用轉換為IOC容器中實例化對象引用
                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);
        }
    }

分析上述代碼,我們可以看出,對屬性的注入過程分以下兩種情況:
1)、屬性值類型不需要強制轉換時,不需要解析屬性值,直接准備進行依賴注入。
2)、屬性值需要進行類型強制轉換時,如對其他對象的引用等,首先需要解析屬性值,然后對解析后的屬性值進行依賴注入。
對屬性值的解析是在 BeanDefinitionValueResolver 類中的 resolveValueIfNecessary()方法中進行的,對屬性值的依賴注入是通過 bw.setPropertyValues()方法實現的,在分析屬性值的依賴注入之前,我們先分析一下對屬性值的解析過程

解析屬性注入規則

當容器在對屬性進行依賴注入時,如果發現屬性值需要進行類型轉換,如屬性值是容器中另一個 Bean實例對象的引用,則容器首先需要根據屬性值解析出所引用的對象,然后才能將該引用對象注入到目標實例對象的屬性上去,對屬性進行解析的由 resolveValueIfNecessary()方法實現。

Spring IOC 容器是如何將屬性的值注入到 Bean 實例對象中去的:
1)、對於集合類型的屬性,將其屬性值解析為目標類型的集合后直接賦值給屬性。
2)、對於非集合類型的屬性,大量使用了 JDK 的反射機制,通過屬性的 getter()方法獲取指定屬性注入以前的值,同時調用屬性的 setter()方法為屬性設置注入后的值。看到這里相信很多人都明白了 Spring的 setter()注入原理

Spring DI運行時序圖


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM