Spring IOC過程源碼解析

廢話很少說,咱們先作一個傻瓜版的IOC demo做爲例子

自定義的Bean定義html

class MyBeanDefinition{

    public String id;
    public String className;
    public String value;

    public MyBeanDefinition(String id, String className, String value) {
        this.id = id;
        this.className = className;
        this.value = value;
    }

}

自定義的Bean工廠node

class MyBeanFactory {

    Map<String, Object> beanMap = new HashMap<>();

    public MyBeanFactory(MyBeanDefinition beanDefinition) throws ClassNotFoundException,
            IllegalAccessException, InstantiationException {

        Class<?> beanClass = Class.forName(beanDefinition.className);
        Object bean = beanClass.newInstance();
        ((UserService) bean).setName(beanDefinition.value);
        beanMap.put(beanDefinition.id, bean);

    }

    public Object getBean(String id) {
        return beanMap.get(id);
    }


}

測試傻瓜版IOC容器spring

public class EasyIOC {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, ClassNotFoundException {

        MyBeanDefinition beanDefinition = new MyBeanDefinition("userService",
                "com.valarchie.UserService", "archie");

        MyBeanFactory beanFactory = new MyBeanFactory(beanDefinition);
        UserService userService = (UserService) beanFactory.getBean("userService");

        System.out.println(userService.getName());

    }


}

看完以上這個傻瓜版的例子咱們能夠思考一下?讓咱們本身實現IOC的容器的關鍵是什麼呢?

按照個人理解,我總結爲如下三步設計模式

  • 讀取xml文件造成DOM對象
  • 讀取DOM文檔對象裏的Bean定義並裝載進BeanFactory中
  • 根據bean定義生成實例放進容器,以供使用

因此,接下來咱們不會通盤分析整個IOC的流程,由於旁枝細節太多讀者看完也雲裏霧裏抓不到重點。
咱們經過分析最重要的這條代碼主幹線來理解IOC的過程。數組

開始分析:

首先咱們從xml的配置方式開始分析,由於Spring最初的配置方式就是利用xml來進行配置,因此大部分人對xml的配置形式較爲熟悉,也比較方便理解。緩存

從ClassPathXmlApplicationContext的構造器開始講起。app

public class TestSpring {
    public static void main(String[] args) {
        // IOC容器的啓動就從ClassPathXmlApplicationContext的構造方法開始
        ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application.xml");
        UserService userService = (UserService) context.getBean("userService");
        System.out.println(userService.getName());
       
    }
}

進入到構造方法中,調用重載的另外一個構造方法。dom

// 建立ClassPathXmlApplicationContext,加載給定的位置的xml文件,並自動刷新context
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
}

重載的構造方法中,因爲剛纔parrent參數傳爲null,因此不設置父容器。refresh剛纔設置爲true,流程就會進入refresh()方法中ide

public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
            throws BeansException {
        // 因爲以前的方法調用將parent設置爲null,因此咱們就不分析了
        super(parent);
        // 設置路徑數組,並依次對配置路徑進行簡單佔位符替換處理,比較簡單,咱們也不進入分析了
        setConfigLocations(configLocations);
        if (refresh) {
            refresh();
        }
}

整個refresh()方法中就是IOC容器啓動的主幹脈絡了,Spring採用了模板方法設計模式進行refresh()方法的設計,先規定好整個IOC容器的具體步驟,而後將每個小步驟由各類不一樣的子類本身實現。post

全部重要的操做都是圍繞着BeanFactory在進行。
在註釋當中,咱們詳細的列出了每一步方法所完成的事情。ApplicationContext內部持有了FactoryBean的實例。其實ApplicationContext自己最上層的父接口也是BeanFactory,他拓展了BeanFactory以外的功能(提供國際化的消息訪問、資源訪問,如URL和文件、事件傳播、載入多個(有繼承關係)上下文)

咱們先經過閱讀代碼中的註釋來了解大概的脈絡。

public void refresh() throws BeansException, IllegalStateException {
        // 先加鎖防止啓動、結束衝突
        synchronized (this.startupShutdownMonitor) {
            // 在刷新以前作一些準備工做
            // 設置啓動的時間、相關狀態的標誌位(活動、關閉)、初始化佔位符屬性源,並確認
            // 每一個標記爲必須的屬性都是可解析的。
            prepareRefresh();

            // 獲取一個已刷新的BeanFactory實例。
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // 定義好Bean工廠的環境特性,例如類加載器,或者後置處理器
            prepareBeanFactory(beanFactory);

            try {
                // 設置在BeanFactory完成初始化以後作一些後置操做,spring留給子類的擴展。
                postProcessBeanFactory(beanFactory);

                // 啓動以前已設置的BeanFactory後置處理器
                invokeBeanFactoryPostProcessors(beanFactory);

                // 註冊Bean處理器
                registerBeanPostProcessors(beanFactory);

                // 爲咱們的應用上下文設置消息源(i18n)
                initMessageSource();

                // 初始化事件廣播器
                initApplicationEventMulticaster();

                // 初始化特殊的Bean在特殊的Context中,默認實現爲空,交給各個具體子類實現
                onRefresh();

                // 檢查監聽器並註冊
                registerListeners();

                // 實例化全部非懶加載的Bean
                finishBeanFactoryInitialization(beanFactory);

                // 最後一步發佈相應的事件
                finishRefresh();
            }

            catch (BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // 若是啓動失敗的話,要銷燬以前建立的Beans。
                destroyBeans();

                // 重置ApplicationContext內部active的標誌位
                cancelRefresh(ex);

                // 向調用者拋出異常
                throw ex;
            }

            finally {
                // 重置Spring核心內的緩存,由於咱們可能再也不須要單例bean相關的元數據
                resetCommonCaches();
            }
        }
    }

閱讀完以後咱們重點關注obtainFreshBeanFactory()、finishBeanFactoryInitialization(beanFactory)這兩個方法,由於實質上整個IOC的流程都在這兩個方法當中,其餘的方法一部分是Spring預留給用戶的自定義操做如BeanFactory的後置處理器和Bean後置處理器,一部分是關鍵啓動事件的發佈和監聽操做,一部分是關於AOP的操做。

首先,先從obtainFreshBeanFactory()開始提及。

第一步:讀取xml文件造成DOM對象

在getBeanFactory()方法以前,先調用refreshBeanFactory()方法進行刷新。咱們先說明一下,getBeanFactory()很是簡單,默認實現只是將上一步刷新成功好構建好的Bean工廠進行返回。返回出去的Bean工廠已經加載好Bean定義了。因此在refreshBeanFactory()這個方法中已經包含了第一步讀取xml文件構建DOM對象和第二步解析DOM中的元素生成Bean定義進行保存。記住,這裏僅僅是保存好Bean定義,此時並未涉及Bean的實例化。

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
}

進入refreshBeanFactory()方法中

protected final void refreshBeanFactory() throws BeansException {
        // 若是當前ApplicationContext中已存在FactoryBean的話進行銷燬
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            // 先生成一個BeanFactory
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            // 設置序列化
            beanFactory.setSerializationId(getId());
            // 設置是否能夠覆蓋Bean定義和是否能夠循環依賴,具體我就不解釋了
            customizeBeanFactory(beanFactory);
            // 加載Bean定義到Factory當中去
            // 重點!
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

接下來,進入核心方法loadBeanDefinitions(beanFactory)中,參數是剛建立的beanFactory

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // 根據傳入的beanfactory建立一個xml讀取器
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    
        // 設置bean定義讀取器的相關資源加載環境
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // 這個方法讓子類自定義讀取器Reader的初始化
        initBeanDefinitionReader(beanDefinitionReader);
        // 接着開始實際加載Bean定義
        loadBeanDefinitions(beanDefinitionReader);
    }

進入loadBeanDefinitions(beanDefinitionReader)方法中,參數是剛剛建立好的Reader讀取器。

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
        // 若是有已經生成好的Resouce實例的話就直接進行解析。
        // 默認的實現是返回null,由子類自行實現。
        Resource[] configResources = getConfigResources();
        if (configResources != null) {
            reader.loadBeanDefinitions(configResources);
        }
        // 沒有Resouces的話就進行路徑解析。
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            reader.loadBeanDefinitions(configLocations);
        }
}

咱們進入reader.loadBeanDefinitions(configLocations)方法中,這裏面方法調用有點繞,我這邊只簡單地描述一下

該方法會根據多個不一樣位置的xml文件依次進行處理。
接着會對路徑的不一樣寫法進行不一樣處理,例如classpath或者WEB-INF的前綴路徑。
根據傳入的locations變量生成對應的Resouces。
緊接着進入reader.loadBeanDefinitions(resource)此時參數是Resource。
在通過一層進入loadBeanDefinitions(new EncodedResource(resource))的方法調用中。

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isInfoEnabled()) {
        logger.info("Loading XML bean definitions from " + encodedResource.getResource());
    }
    // 經過ThreadLocal實現的當前currentResource
    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (currentResources == null) {
        currentResources = new HashSet<EncodedResource>(4);
        this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException(
                "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {
    
        // 最主要的方法在這段
        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            // 傳入流對象,並設置好編碼
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
        }
        finally {
            inputStream.close();
        }
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(
                "IOException parsing XML document from " + encodedResource.getResource(), ex);
    }
    finally {
        currentResources.remove(encodedResource);
        if (currentResources.isEmpty()) {
            this.resourcesCurrentlyBeingLoaded.remove();
        }
    }
}

該方法最主要是建立了對應的輸入流,並設置好編碼。

而後開始調用doLoadBeanDefinitions()方法。

// 內部核心代碼就這兩句
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);

在loadDocument()方法中會生成一個DocumentBuilderImpl對象,這個對象會調用parse方法,在parse方法中使用SAX進行解析剛纔的輸入流包裝的InputSource,生成DOM對象返回。

public Document parse(InputSource is) throws SAXException, IOException {
        if (is == null) {
            throw new IllegalArgumentException(
                DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
                "jaxp-null-input-source", null));
        }
        if (fSchemaValidator != null) {
            if (fSchemaValidationManager != null) {
                fSchemaValidationManager.reset();
                fUnparsedEntityHandler.reset();
            }
            resetSchemaValidator();
        }
        // 解析xml
        domParser.parse(is);
        // 獲取剛纔解析好的dom
        Document doc = domParser.getDocument();
        domParser.dropDocumentReferences();
        return doc;
}

此時咱們的xml文件已經加載並解析成DOM結構對象了,第一步已經完成了。

第二步:讀取DOM文檔對象裏的Bean定義並裝載進BeanFactory中

// 內部核心代碼就這兩句
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);

咱們再回到剛剛講到的這兩句核心代碼,第一句獲取DOM對象後,緊接着第二句registerBeanDefinitions(doc, resource)開始了bean定義的註冊工做。

進入registerBeanDefinitions(doc, resource)方法中

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        // 生成DOM讀取器,這個和剛纔的讀取器不同,以前的讀取器是xml讀取器。
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        // 獲取以前的bean定義數量 
        int countBefore = getRegistry().getBeanDefinitionCount();
        
        // 進入重點
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        
        // 用剛剛又建立的bean定義數量 - 以前的bean定義數量 = 剛剛一共建立的bean定義 
        return getRegistry().getBeanDefinitionCount() - countBefore;
}

進入documentReader.registerBeanDefinitions(doc, createReaderContext(resource))方法。
方法內讀取文檔的root元素。

protected void doRegisterBeanDefinitions(Element root) {
        // Any nested <beans> elements will cause recursion in this method. In
        // order to propagate and preserve <beans> default-* attributes correctly,
        // keep track of the current (parent) delegate, which may be null. Create
        // the new (child) delegate with a reference to the parent for fallback purposes,
        // then ultimately reset this.delegate back to its original (parent) reference.
        // this behavior emulates a stack of delegates without actually necessitating one.
        BeanDefinitionParserDelegate parent = this.delegate;
        
        // 生成Bean定義解析類
        this.delegate = createDelegate(getReaderContext(), root, parent);

        // 若是是xml文檔中的namespace,進行相應處理
        if (this.delegate.isDefaultNamespace(root)) {
            String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
            if (StringUtils.hasText(profileSpec)) {
                String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
                        profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
                if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
                                "] not matching: " + getReaderContext().getResource());
                    }
                    return;
                }
            }
        }

        // spring預留給子類的拓展性方法
        preProcessXml(root);
        
        // 重點
        // 開始解析Bean定義
        parseBeanDefinitions(root, this.delegate);
        
      // spring預留給子類的拓展性方法
        postProcessXml(root);

        this.delegate = parent;
        
}

進入parseBeanDefinitions(root, this.delegate)。將以前的文檔對象和bean定義解析類做爲參數傳入。

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
        if (delegate.isDefaultNamespace(root)) {
            NodeList nl = root.getChildNodes();
            // 遍歷去解析根節點的每一個子節點元素
            for (int i = 0; i < nl.getLength(); i++) {
                Node node = nl.item(i);
                // 若是是標籤元素的話
                if (node instanceof Element) {
                    Element ele = (Element) node;
                    if (delegate.isDefaultNamespace(ele)) {
                    
                        // 解析默認的元素
                        // 重點
                        parseDefaultElement(ele, delegate);
                    }
                    else {
                        // 解析指定自定義元素
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
        else {
            // 非默認命名空間的,進行自定義解析,命名空間就是xml文檔頭內的xmlns,用來定義標籤。
            delegate.parseCustomElement(root);
        }
}

進入到parseDefaultElement(ele, delegate)當中,會發現其實對四種標籤進行分別的解析。

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            // 分析Bean標籤
            processBeanDefinition(ele, delegate);
        }
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            // recurse
            doRegisterBeanDefinitions(ele);
        }
}

咱們主要分析Bean元素標籤的解析,進入processBeanDefinition(ele, delegate)方法中最內層。

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
        // 獲取bean標籤內的id
        String id = ele.getAttribute(ID_ATTRIBUTE);
        // 獲取bean標籤內的name
        String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

        // 設置多別名
        List<String> aliases = new ArrayList<String>();
        if (StringUtils.hasLength(nameAttr)) {
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            aliases.addAll(Arrays.asList(nameArr));
        }

        // 當沒有設置id的時候
        String beanName = id;
        if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
            beanName = aliases.remove(0);
            if (logger.isDebugEnabled()) {
                logger.debug("No XML 'id' specified - using '" + beanName +
                        "' as bean name and " + aliases + " as aliases");
            }
        }

        // 檢查beanName是否惟一
        if (containingBean == null) {
            checkNameUniqueness(beanName, aliases, ele);
        }
        // 內部作了Bean標籤的解析工做
        AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
        if (beanDefinition != null) {
            if (!StringUtils.hasText(beanName)) {
                try {
                    if (containingBean != null) {
                        beanName = BeanDefinitionReaderUtils.generateBeanName(
                                beanDefinition, this.readerContext.getRegistry(), true);
                    }
                    else {
                        beanName = this.readerContext.generateBeanName(beanDefinition);
                        // Register an alias for the plain bean class name, if still possible,
                        // if the generator returned the class name plus a suffix.
                        // This is expected for Spring 1.2/2.0 backwards compatibility.
                        String beanClassName = beanDefinition.getBeanClassName();
                        if (beanClassName != null &&
                                beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                                !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                            aliases.add(beanClassName);
                        }
                    }
                    if (logger.isDebugEnabled()) {
                        logger.debug("Neither XML 'id' nor 'name' specified - " +
                                "using generated bean name [" + beanName + "]");
                    }
                }
                catch (Exception ex) {
                    error(ex.getMessage(), ele);
                    return null;
                }
            }
            String[] aliasesArray = StringUtils.toStringArray(aliases);
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        }

        return null;
}

將解析好的Bean定義並附加別名數組填入new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray)中進行返回。而後調用如下這個方法。

BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())

最主要的操做就是將剛纔解析好的Bean定義放入beanDefinitionMap中去。

解析成功後將Bean定義進行保存。第二步也已經完成。

第三步:使用建立好的Bean定義,開始實例化Bean。

咱們回到最開始的refresh方法中,在finishBeanFactoryInitialization(beanFactory)方法中,開始實例化非懶加載的Bean對象。咱們跟着調用鏈進入到preInstantiateSingletons()方法中

@Override
public void preInstantiateSingletons() throws BeansException {
    if (this.logger.isDebugEnabled()) {
        this.logger.debug("Pre-instantiating singletons in " + this);
    }

    // 將以前作好的bean定義名列表拷貝放進beanNames中,而後開始遍歷
    List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

    // 觸發全部非懶加載的單例Bean實例化
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        
        // 若是非抽象而且是單例和非懶加載的話
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
            // 檢測是不是工廠方法Bean。 建立Bean的不一樣方式,讀者可自行百度。
            if (isFactoryBean(beanName)) {
                final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                    isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                        @Override
                        public Boolean run() {
                            return ((SmartFactoryBean<?>) factory).isEagerInit();
                        }
                    }, getAccessControlContext());
                }
                else {
                    isEagerInit = (factory instanceof SmartFactoryBean &&
                            ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
                    getBean(beanName);
                }
            }
            else {
                getBean(beanName);
            }
        }
    }

    // 關於實例化以後作的自定義操做代碼省略....
}

在該方法中根據Bean實例是經過工廠方法實例仍是普通實例化,最主要的方法仍是getBean(beanName)方法。咱們繼續分析普通實例化的過程。進入getBean()方法當中doGetBean()方法,發現方法參數doGetBean(name, null, null, false)後三個參數所有爲null,它就是整個IOC中的核心代碼。

代碼中先經過實例化Bean,實例化好以後再判斷該Bean所需的依賴,並遞歸調用進行實例化bean,成功後整個IOC的核心流程也就完成了。

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;

    // Eagerly check singleton cache for manually registered singletons.
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isDebugEnabled()) {
            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 = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
        // 若是當前Bean正在建立中的話就直接失敗,
        // 能夠陷入了循環引用。
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // 檢測Bean定義是否出如今父Bean工廠
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // 父工廠不爲null而且當前不包含這個Bean定義時
            // 從父工廠去返回Bean
            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);
            }
        }

            // 若是不須要類型檢查的話 標記爲已建立
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        try {
            // 將子Bean定義與父Bean定義進行整合
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 整合後若是發現是抽象類不能實例 拋出異常
            checkMergedBeanDefinition(mbd, beanName, args);

            // 獲取Bean定義所需的依賴並逐一初始化填充
            String[] dependsOn = mbd.getDependsOn();
            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 + "'");
                    }
                    // 註冊依賴的Bean
                    registerDependentBean(dep, beanName);
                    try {
                    // 遞歸調用生成所需依賴的Bean
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // 若是是單例的話
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    @Override
                    public Object getObject() throws BeansException {
                        try {
                            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.
                            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 {
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                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) {
                    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;
        }
    }

    // 檢測實例Bean的類型和所需類型是否一致
    if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
        try {
            return getTypeConverter().convertIfNecessary(bean, requiredType);
        }
        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;
}

根據Bean定義去實例化Bean。第三步也已經完成。

文章篇幅有限,IOC整個的建立過程仍是比較冗長的,但願讀者看完文章對IOC的建立過程有一個主幹脈絡的思路以後仍是須要翻開源碼進行解讀,其實閱讀源碼並不難,由於Spring的代碼註釋都挺健全,若是遇到不清楚的稍微google一下就知道了。建議讀者本身試着一步一步的分析IOC過程的源碼。

轉自個人我的博客 vc2x.com

相關文章
相關標籤/搜索