1. 程式人生 > >IOC容器的依賴注入

IOC容器的依賴注入

IOC的依賴注入(原始碼分析)

前面的IOC容器的初始化,已經完成了BeanDefination的資料對映,將BeanDefination設定beanDefinitionMap中,現在資料已經有了,但是還沒有注入到容器中,下面看下如何進行注入。

依賴注入過程:

IOC容器依賴注入時序圖

在前面的BeanFactory介面中經常看到getBean()方法,現在看下在AbstractBeanFactory中對getBean()的具體實現:

  • AbstractBeanFactory#getBean()入口
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false); } @Override public <T> T getBean(String name, Class<T> requiredType) throws BeansException { return doGetBean(name, requiredType, null, false); } @Override public Object getBean(String name, Object... args) throws BeansException { return
doGetBean(name, null, args, false); }

首先getBean都是委託doGetBean方法來實現的,在Spring的原始碼中有很多很多這種方式,我們可以在實際專案應用中來借鑑。(我們主要看主線,我這邊會將一些引數的校驗以及丟擲的異常省略,有興趣的朋友可以進原始碼詳細看)

protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name); Object bean; //先從快取中獲取bean,處理那些已經被建立過的bean,避免重複建立bean。 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { //此處省去日誌的列印... //完成對FactoryBean的相關處理取得FactoryBean物件,後續會詳細解釋FactoryBean。 bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { //判斷是否已經建立過bean,如果建立過則丟擲異常 if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } //判斷bean是夠在當前的BeanFactory中,如果不在則到雙親的BeanFactory中去獲取,如果雙親沒有,則一直往上去找。 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); 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為已建立bean if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { //根據beanName獲取BeanDefination final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); //獲取當前bean的所有的依賴bean,如果有依賴,則會進行遞迴呼叫getBean方法,遞迴建立依賴的bean物件。 String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { //如果是迴圈依賴,則丟擲異常(省去異常資訊...) } //註冊依賴bean registerDependentBean(dep, beanName); getBean(dep); } } //建立bean例項,主要是通過createBean方法來處理,後面會單獨拿出來看。 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { destroySingleton(beanName); throw ex; } } }); bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { //其他模式下的bean的建立 String scopeName = mbd.getScope(); final Scope scope = this.scopes.get(scopeName); if (scope == null) { //....異常 } try { Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { @Override public Object getObject() throws BeansException { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { //....非法異常 } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName); throw ex; } } //檢測建立的bean的型別 if (requiredType != null && bean != null && !requiredType.isInstance(bean)) { try { return getTypeConverter().convertIfNecessary(bean, requiredType); } catch (TypeMismatchException ex) { //....log throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }
  • AbstractAutowireCapableBeanFactory#createBean()建立bean例項
/**
* Central method of this class: creates a bean instance,
* populates the bean instance, applies post-processors, etc.
* 此類的主要方法:建立Bean例項,填充bean例項,應用後置處理bean等等
* @see #doCreateBean
*/
@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使用overrides 過載方法是否合法(未過載則提示錯誤)
    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.
        //為BeanPostProcessors提供返回代理而不是目標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建立的呼叫,實際的處理還是委託doCreateBean()方法來處理
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isDebugEnabled()) {
            logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        // A previously detected exception with proper bean creation context already,
        // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}

AbstractAutowireCapableBeanFactory#doCreateBean()建立bean例項

/**
* 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
*/
//實際建立bean的地方,此時預處理已經完成了。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
    throws BeanCreationException {

    // 持有例項化的bean
    BeanWrapper instanceWrapper = null;
    //如果是單例,則刪除快取中的這個beanName例項
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        //建立bean例項
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    //拿到此物件包裝的bean的例項
    final Object bean = instanceWrapper.getWrappedInstance();
    //拿到此物件包裝的bean的型別
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    //允許後處理器修改合併的bean定義。
    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.
    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例項物件
    Object exposedObject = bean;
    try {
        //填充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) {
        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<>(dependentBeans.length);
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
               //省去實際依賴bean為空的異常處理...
            }
        }
    }

    // Register bean as disposable.
    try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

大致可以理一下,與依賴注入有關的比較重要的方法createBeanInstancepopulateBean

  • createBeanInstance建立bean的例項,生成了Bean所包含的所有的物件。下面看下原始碼:

    /**
    * 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 a BeanWrapper for the new instance
    * @see #obtainFromSupplier
    * @see #instantiateUsingFactoryMethod
    * @see #autowireConstructor
    * @see #instantiateBean
    */
    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);
    
        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());
        }
    
        //Spring 5.0 新增的例項化策略,如果設定了該策略,將會覆蓋構造方法和工廠方法例項化策略
        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        if (instanceSupplier != null) {
            return obtainFromSupplier(instanceSupplier, beanName);
        }
    
        //如果工廠不為空,則使用工廠方法對Bean進行例項化
        if (mbd.getFactoryMethodName() != null)  {
            return instantiateUsingFactoryMethod(beanName, mbd, args);
        }
    
        // Shortcut when re-creating the same bean...
        // 當建立一個相同的bean時,使用之間儲存的快照
        // 這裡可能會有一個疑問,什麼時候會建立相同的bean呢?
        //單例模式: Spring不會快取該模式的例項,那麼對於單例模式的bean,什麼時候會用到該例項化策略呢?
        //我們知道對於IoC容器除了可以索取bean之外,還能銷燬bean,當我們呼叫xmlBeanFactory.destroyBean(myBeanName,myBeanInstance),
        //銷燬bean時,容器是不會銷燬已經解析的建構函式快照的,如果再次呼叫xmlBeanFactory.getBean(myBeanName)時,就會使用該策略了.
        // 		③-->② 原型模式: 對於該模式的理解就簡單了,IoC容器不會快取原型模式bean的例項,當我們第二次向容器索取同一個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);
            
                
               

    相關推薦

    Spring Ioc容器依賴注入

    1、時序圖 IOC容器的依賴注入是建立在資料BeanDefinition準備好的前提之下的。依賴注入的發生有兩種情況:系統第一次向容器索要bean的時候;bean在配置的時候設定了Lazy-init屬性,該屬性會讓容器完成預例項化,預例項化就是一個依賴注入的過程。Bean

    SpringBoot啟動流程分析(六):IoC容器依賴注入

    SpringBoot系列文章簡介 SpringBoot原始碼閱讀輔助篇:   Spring IoC容器與應用上下文的設計與實現 SpringBoot啟動流程原始碼分析: SpringBoot啟動流程分析(一):SpringApplication類初始化過程 SpringBoot啟動流程分析(二)

    深入理解spring容器中的控制反轉(IOC)和依賴注入(DI)

    首先在開篇之前我們一定一定要明確的就是:DI和IOC並不是兩個概念,DI是IOC思想在應用上的具體例子。 什麼是控制反轉(IOC)? “控制”就是指一件事物對另一件事物進行一種管理,而另一件事物處在一件事物的管理之下,這就叫控制。 在面向物件程式設計的時候,每一個程式的

    Spring IOC原始碼詳解之容器依賴注入

    進入BeanWrapperImpl public class BeanWrapperImpl extends AbstractNestablePropertyAccessor implements BeanWrapper BeanWrapperImpl繼承了AbstractNestablePropert

    1.Spring、IOC依賴注入

     Spring概述 Spring是分層的Java SE/EE應用 full-stack輕量級開源框架,以IoC(Inverse Of Control:反轉控制)和 AOP(Aspect Oriented Programming:面向切面程式設計)為核心,提供了展現層Spr

    Spring基於註解 的IOC依賴注入

    新建 project maven## 標題 初識 註解的 開發 是:將 熟悉的 xml 結合的 完成學習的 –>(需要官方的文件支援 沒有:不能執行) 》AOPjar包 的 -----xml 的配置–告知Spring要掃描的 包 xml 約束 檔案 ----

    單元測試(Junit)使用及Junit支援Spring IOC依賴注入

    單元測試在我們日常寫程式碼的過程中特別重要,可以儘快發現區域性的程式碼問題 Junit是我經常使用的一種單元測試工具 下面先寫一個單元測試的示例 先寫一個提供呼叫方法的類 package test; /** * @author coder * @version v

    IOC容器注入方式

    IOC和DI IOC:   反轉資源獲取的方向 DI:   IOC的另一種表述反式,即元件以一些預先定義好的方式(例如:setter方法)接收來自如容器的資源注入 IOC容器物件的關聯關係 IOC前生--分離介面與實現 IOC前生--採用工廠設計模式 IOC前生--採用反轉控制 配置Bean

    Spring的控制反轉IOC依賴注入DI

    首先想說說IoC(Inversion of Control,控制反轉)。這是spring的核心,貫穿始終。所謂IoC,對於spring框架來說,就是由spring來負責控制物件的生命週期和物件間的關係: 誰控制誰,控制什麼:傳統Java SE程式設計,我們直接在物件內部通過new進行

    控制反轉(IoC)和依賴注入(DI)

    容器,字面上理解就是裝東西的東西。常見的變數、物件屬性等都可以算是容器。一個容器能夠裝什麼,全部取決於你對該容器的定義。當然,有這樣一種容器,它存放的不是文字、數值,而是物件、物件的描述(類、介面)或者是提供物件的回撥,通過這種容器,我們得以實現許多高階的功能,其中最常提到的,就是 “解耦” 、“依

    控制反轉IOC依賴注入方式 【調侃】IOC前世今生 IoC模式 談談對Spring IOC的理解 一個簡單的小程式演示Unity的三種依賴注入方式 小菜學習設計模式(五)—控制反轉(IocIoC模式(依賴依賴倒置、依賴注入、控制反轉) IoC模式

    轉自:https://www.cnblogs.com/ysyn/p/5563256.html 引言:    專案中遇到關於IOC的一些內容,因為和正常的邏輯程式碼比較起來,IOC有點反常。因此本文記錄IOC的一些基礎知識,並附有相應的簡單例項,而在實際專案中再複雜的應用也只是在

    AutoFac (控制反轉IOC依賴注入DI) 優化

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FB.CMS.Repository { usin

    10、IoC依賴注入(3)-解析注入的屬性

    對於屬性注入的間接引用,具體的解析過程是在BeanDefinitionValueResolver類中的resolveValueIfNecessary方法中實現的,主要解析Array,Set,Map,props和字串型別的間接引用。具體實現原始碼如下: // BeanDe

    Spring.net 控制反轉(IOC依賴注入(DI)的使用 以及Config檔案的配置

                                                      IOC 一 、把   \Spring.Net\Spring.NET-2.0.0-M1\Spring.NET\bin\net\4.0\release下的 三個核心檔案   S

    控制反轉(IoC)以及依賴注入(DI)的解釋

    理解IoC和DI對於Spring的初學者來說是很重要的. 剛開始接觸到這兩個詞感覺過於抽象實在難懂,會有很多問題產生,什麼叫反轉?什麼是依賴關係,啥又叫注入? 程式設計師都是懶惰和高冷的 記住這句話,因此一個純粹的程式設計師都會想方設法讓自己的程式碼變得簡潔,並且後期修改的

    AutoFac IoC DI 依賴注入

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Optim

    Spring框架學習筆記(1)——控制反轉IOC依賴注入DI

    Spring框架的主要作用,就是提供了一個容器,使用該容器就可以建立並管理物件。比如說Dao類等,又或者是具有多依賴關係的類(Student類中包含有Teacher類的成員變數) Spring有兩個核心概念,一個是控制反轉(IOC,全稱為Inverse of Control),另一個則是面向切面程式設計(AO

    .NET IoC模式依賴反轉(DIP)、控制反轉(Ioc)、依賴注入(DI)

    # 依賴倒置原則(DIP) 依賴倒置(Dependency Inversion Principle,縮寫DIP)是面向物件六大基本原則之一。他是指一種特定的的解耦形式,使得高層次的模組不依賴低層次的模組的實現細節,依賴關係被顛倒(反轉),從而使得低層次模組依賴於高層次模組的需求抽象. 該原則規定: -

    SpringFramework的核心:IOC容器的實現------IoC容器依賴注入

    如果IoC容器已經載入了使用者定義的Bean資訊,並開始分析依賴注入的原理。依賴注入是使用者第一次向IoC容器索要Bean時觸發的,當然也有例外。如果我們設定了lazy-init的屬性。是可以在剛開始初始化容器的時候就為我們生成新的bean。 首先我們從DefaultListableBean

    4. IOC容器依賴注入(原始碼解讀)

    一、基本概念 1.當Spring IoC容器完成了Bean定義資源的定位、載入和解析註冊以後,IoC容器中已經管理類Bean定義的相關資料,但是此時IoC容器還沒有對所管理的Bean進行依賴注入,依賴注入在以下兩種情況發生: (1)使用者第一次通過getBean