Spring源碼解析系列之IOC容器(一)

前言

實(shí)際上我所有的博客都是原來對原來印象筆記里筆記內(nèi)容的加工,關(guān)于Spring源碼自己已經(jīng)解析了很多遍,但是時間長總是忘記,寫一篇博客權(quán)當(dāng)加強(qiáng)記憶,也算再次學(xué)習(xí)下大師們的設(shè)計思想,思考方式。本次源碼解析對最底層的如怎么讀取xml文件等不做詳細(xì)解釋,只分析關(guān)鍵步驟和思想。

1、Spring整體架構(gòu)

Spring整體架構(gòu)

Spring由很多模塊組成,我們不可能挨個模塊去看源碼去分析,看源碼本身就是一件及其枯燥乏味的事情。言簡意賅,咱們Spring源碼解析系列只挑干貨,即Core Container模塊的IOC依賴注入,AOP模塊的面向切面編程,DataAccess模塊的Trasactions事務(wù)原理和web模塊的mvc原理部分。而且分析也盡量偏向重要步驟和思想,而不是干巴巴的啃源碼。
源碼分析思路:
首先:確定IOC容器做了什么,其實(shí)主要是加載和管理bean
然后:找到做這些事情的所有頂層接口
再次:找頂層接口的干不同事情的子類、分析這些子類是做什么的
最后:挑最富有內(nèi)涵的接口分析其原理和思想,學(xué)習(xí)他們的設(shè)計思路

2、IOC容器

2.1、IOC的概念

IOC即依賴注入、控制反轉(zhuǎn),兩個概念都一樣,即把創(chuàng)建Java對象和維持對象的依賴關(guān)系的活兒交給Spring來做,把對對象的控制權(quán)交給Spring、讓對象減少耦合。我們這里把IOC叫做容器,即容納Java Bean的容器。IOC容器里面所有能提供服務(wù)的對象都叫Bean,至于怎么配置Bean這里就不過多贅述了,如果你不知道通過xml和注解配置bean那么你不應(yīng)該來看源碼。

2.2、bean的幾種形態(tài)

IOC里最重要的概念就是Bean,所有的接口都圍繞Bean確立,在真正分析之前我們先看看Bean的幾種形態(tài)。

  • 形態(tài)一:xml或者注解標(biāo)注的概念態(tài),此時bean只是一個由類和一些描述文件定義的概念狀態(tài),比如:
<bean id="schedulerFactoryBean"
        class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="jobFactory" ref="jobFactory"></property>
</bean>
  • 形態(tài)二:內(nèi)存中的定義態(tài),此時Bean被加載到內(nèi)存中,但還處在BeanDefinition這種定義狀態(tài),這種狀態(tài)實(shí)際上是bean創(chuàng)建的模板。
  • 形態(tài)三:純凈態(tài),此時的Bean只是被Bean工廠創(chuàng)建成了對象,但是并沒有給bean的每個屬性賦值,此時各屬性還處于0 null false等這種初始狀態(tài),想想無參構(gòu)造函數(shù)創(chuàng)建的對象。
  • 形態(tài)四:成熟態(tài),純凈的Bean的屬性被賦予真實(shí)有效的值,此時的Bean就是我們最終要使用的狀態(tài),已經(jīng)可以提供正常服務(wù)了。
2.3、bean相關(guān)重要接口

了解了Bean的幾個狀態(tài)后我們至少能想到幾個重要的接口。

  • 接口一:Resource接口,能把xml等文件讀取到內(nèi)存中,并能夠獲取到xml文件的詳細(xì)信息。
  • 接口二:Document接口,用于xml文件解析到內(nèi)存,類似于js里的dom解析。
  • 接口三:BeanDefinitionReader接口,用于解析xml和加載Bean成為BeanDefinition
  • 接口四:BeanDefinition接口,bean的抽象定義,如是否單例,是否是懶加載,有哪些重要屬性等等。
  • 接口五:BeanFactory,Spring里面的重要模式-工廠模式,用于創(chuàng)建真正意義上的bean類。
  • 接口六:ApplicationContext,應(yīng)用程序上下文,我一般都把上下文理解成容器,這個容器就是bean真正運(yùn)行的容器,spring機(jī)器也由此啟動。
2.4、bean創(chuàng)建步驟
2.4.1、創(chuàng)建步驟

上面我們了解了Bean的狀態(tài)和幾個處理Bean的工具,接著我們就看Bean是怎么從概念態(tài)變成可用的成熟態(tài)的。此處我們先以xml配置的bean為例子。

  • 步驟一:資源以統(tǒng)一資源接口Resource加載入內(nèi)存,即利用Resource接口及其子類把xml加載到內(nèi)存中。(形態(tài)一
  • 步驟二:把Resource處理成Document,然后根據(jù)Dom接口處理Element節(jié)點(diǎn)即可,然后校驗,校驗過程根據(jù)DTD和XSD也就是ApplicationContext頭部的配置進(jìn)行xml格式校驗
  • 步驟三:解析,解析過程包括bean的id,property以及其他方面的配置,把資源中的bean和其他標(biāo)簽(是否懶加載,是否單例等)解析成BeanDefinition格式(形態(tài)二
  • 步驟四:注冊、就是放到全局的Map中,不過注冊之前做了重名校驗,注冊的方式有別名和bean名兩種
  • 步驟五:解析注冊完成之后通知監(jiān)聽器,這里只為后期擴(kuò)展用,程序員可以實(shí)現(xiàn)相關(guān)監(jiān)聽器方法對這個事件進(jìn)行處理
  • 步驟六:加載,加載步驟:注意:此時加載的Bean還沒有被裝載數(shù)據(jù),還處于(形態(tài)三)純凈態(tài)
    (1):轉(zhuǎn)換對應(yīng)的beanname,也就是獲取最終的beanname,別名轉(zhuǎn)換,去掉無效標(biāo)識符等
    (2):嘗試從緩存中加載單例
    (3):Bean的實(shí)例化
    (4):原型模式的依賴檢查
    (5):檢測ParentBeanFactory,如果當(dāng)前檢測到的xml文件中不包含BeanName,就去父Factory中獲取
    (6):將存儲XML配置文件的GernericBeanDefinition轉(zhuǎn)換為RootBeanDefinition
    (7):尋找依賴,先加載依賴的Bean
    (8):針對不同的scope進(jìn)行bean的創(chuàng)建singleton,request等
    (9):類型轉(zhuǎn)換
  • 步驟七:步驟六弄完bean就是成熟態(tài)了(形態(tài)四
2.4.2、方法調(diào)用鏈:

為了更好的閱讀源碼,此處先給出方法調(diào)用鏈


spring方法調(diào)用鏈.png
2.5、源碼解讀

在開始閱讀源碼之前我們先來看看重要接口的繼承體系(圖片來源于網(wǎng)絡(luò),侵刪)

  • A:Resource接口繼承體系


    Resource接口UML圖

    這個繼承體系里有很多接口,但我們常用的接口是圖中的藍(lán)色部分,其中每個類都對應(yīng)一種資源加載方式,比如URLResource可以從網(wǎng)絡(luò)獲取ApplicationContext.xml文件,F(xiàn)ileSystemResource可以從本地文件系統(tǒng)獲取xml。

  • B:BeanDefinitionReader接口繼承體系


    BeanDefinitionReader接口繼承體系

    這個體系就比較清楚了,XmlBeanDefinitionReader可以把xml文件中的bean加載到內(nèi)存中,并可以處理Document文件。

  • C:BeanDefinition接口繼承體系


    BeanDefinition接口繼承體系

    直接關(guān)注RootBeanDefinition,該類利用其每個父類接口的技能來包裝Bean的定義。比如定義xml的bean,還可以定義注解的bean。

  • D:BeanFactory接口繼承體系


    BeanFactory接口繼承體系

    BeanFactory接口里定義了多個BeanFactory,本質(zhì)上是利用了設(shè)計模式基本原則里面的單一職責(zé)原則與接口隔離原則,簡單來說就是每個接口都只干好自己的一灘事兒。比如:ListableBeanFactory可以枚舉所有的BeanDefinition、AutowireCapableBeanFactory定義了各種裝配規(guī)則,可以自動裝配Bean、ConfigurableBeanFactory可配置的BeanFactory。他們的子類DefaultListableBeanFactory可以用調(diào)用每個接口的方法去應(yīng)對不同的環(huán)境。就像郭靖有江南七怪七個老師,每個老師都有不同技能,所以郭靖可以對不同的環(huán)境使用不同老師的技能。

  • E:ApplicationContext接口繼承體系


    ApplicationContext繼承體系

    這個繼承體系看起來復(fù)雜,但實(shí)際上許多類本質(zhì)上是不同應(yīng)用環(huán)境下的不同容器而已,比如WebApplication是應(yīng)用于web應(yīng)用中的Ioc容器、ClassPathXmlApplicationContext可以以項目中的.xml文件的配置創(chuàng)建一個IOC容器、FileSystemXMLApplicationContext可以根據(jù)磁盤的絕對路徑獲取.xml文件配置一個IOC容器。


源碼解讀開始(以ClassPathXmlApplicationContext為例)

step1:首先創(chuàng)建并初始化一個ClassPathXml的IOC容器

public class HelloProgram {
    public static void main(String[] args) {
        //創(chuàng)建IOC容器
        ApplicationContext context =new ClassPathXmlApplicationContext("beans.xml");
        HelloWorldService service =(HelloWorldService) context.getBean("helloWorldService");
        HelloWorld hw= service.getHelloWorld();
        hw.sayHello();
    }
}
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
        this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
 //父容器被設(shè)置為Null
        super(parent);
//存儲了xml的位置,以便后續(xù)獲取
        setConfigLocations(configLocations);
        if (refresh) {
//常規(guī)操作,初始化容器,如果之前存在就銷毀,不存在就創(chuàng)建
            refresh();
    }
}
    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // 預(yù)初始化,設(shè)置容器的啟動時間、激活標(biāo)志,初始化和驗證一些預(yù)定義的屬性(有的話)
            prepareRefresh();

            // 初始化BeanFactory,存在則銷毀,不存在則創(chuàng)建一個
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // 對即將在IOC容器里使用的BeanFactory做一些配置,比如設(shè)置類加載器,設(shè)置回調(diào)方法等
            prepareBeanFactory(beanFactory);

            try {
                // BeanFactory構(gòu)建完成之后事件,這個方法沒有實(shí)現(xiàn),我們可以實(shí)現(xiàn)一個。
                postProcessBeanFactory(beanFactory);

                // I執(zhí)行上面的事件
                invokeBeanFactoryPostProcessors(beanFactory);

                // 在創(chuàng)建Bean過程中注冊攔截器,這些個攔截器會在bean成為真正的成熟bean(applicationContext管理的bean)之前調(diào)用
                registerBeanPostProcessors(beanFactory);

                // 初始化信息源,信息源bean可以國際化的讀取properties文件
                initMessageSource();

                // 初始化事件廣播器,對于他內(nèi)部的監(jiān)聽者applicationListeners,每次事件到來都會一一獲取通知(這里使用了觀察者模式)
                initApplicationEventMulticaster();

                // 模板方法模式,埋了一個鉤子,那些想要實(shí)現(xiàn)特殊實(shí)例化bean的類可以重寫這個方法以實(shí)現(xiàn)自己的定制化初始化方案
                onRefresh();

                // 給事件廣播器注冊一些監(jiān)聽器(觀察者模式)
                registerListeners();

                // 完成BeanFacotry的初始化,初始化所有剩余的單例Bean
                finishBeanFactoryInitialization(beanFactory);

                //初始化容器的生命周期事件處理器,并發(fā)布容器的生命周期事件 
                finishRefresh();
            }

            catch (BeansException ex) {
                logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);

                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }
        }
    }

obtainFreshBeanFactory方法調(diào)用鏈

該方法為BeanFactory準(zhǔn)備創(chuàng)建Bean的原材料,即BeanDefinition,準(zhǔn)備好之后放到一個ConcurrentHashMap里面,key為beanName,value為BeanDefinition

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }
protected final void refreshBeanFactory() throws BeansException {
        //如果已經(jīng)存在BeanFactory那么就銷毀
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            //創(chuàng)建一個默認(rèn)的BeanFactory,即全功能的那個郭靖!
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            //配置beanFactory的一些定制化屬性,如是否允許循環(huán)依賴,是否支持definition重寫
            customizeBeanFactory(beanFactory);
            //這步就關(guān)鍵了,載入BeanDefinations,給BeanFactory工廠提供創(chuàng)建bean的原材料!
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // 為當(dāng)前工廠創(chuàng)建一個BeanDefinition讀取器!
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // 根據(jù)Contextn的資源對該讀取器進(jìn)行配置,得告訴他去哪讀啊,怎么讀?。?        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // 這里可以設(shè)置一個定制化的Reader
        initBeanDefinitionReader(beanDefinitionReader);
        //此處調(diào)用了重載的方法,把已經(jīng)裝飾好的能用的BeanDefinitionReader讀取器當(dāng)參數(shù)傳了進(jìn)去
        loadBeanDefinitions(beanDefinitionReader);
    }
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
        //這里的reader已經(jīng)可以正常干活兒了,首先獲取bean定義資源
        Resource[] configResources = getConfigResources();
        if (configResources != null) {
            reader.loadBeanDefinitions(configResources);
        }
        //顯然這個configRuations我們之前給傳了一個路徑"bean.xml",所以執(zhí)行這個重載方法
        String[] configLocations = getConfigLocations();
        if (configLocations != null) {
            reader.loadBeanDefinitions(configLocations);
        }
    }
    @Override
    public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
        Assert.notNull(locations, "Location array must not be null");
        int counter = 0;
        for (String location : locations) {
            counter += loadBeanDefinitions(location,null);
        }
        return counter;
    }

尼瑪,套路好深,一個loadBeanDefinition搞這么多重載方法,擦得,總算到底了

public int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {
        ResourceLoader resourceLoader = getResourceLoader();
        if (resourceLoader == null) {
            throw new BeanDefinitionStoreException(
                    "Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
        }

        if (resourceLoader instanceof ResourcePatternResolver) {
            // Resource pattern matching available.
            try {
                Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
                int loadCount = loadBeanDefinitions(resources);
                if (actualResources != null) {
                    for (Resource resource : resources) {
                        actualResources.add(resource);
                    }
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
                }
                return loadCount;
            }
            catch (IOException ex) {
                throw new BeanDefinitionStoreException(
                        "Could not resolve bean definition resource pattern [" + location + "]", ex);
            }
        }
        else {
            // Can only load single resources by absolute URL.
            Resource resource = resourceLoader.getResource(location);
            int loadCount = loadBeanDefinitions(resource);
            if (actualResources != null) {
                actualResources.add(resource);
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
            }
            return loadCount;
        }
    }

忽略我上面說的到底了,尼瑪?。。?!到這應(yīng)該算是到底了吧,這里調(diào)用的是XMLBeanDefinitionReader中的loadBeanDefinitions方法,里邊用IO流來讀取文件

//該方法從我們指定的路徑里獲取xml的bean!?。?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());
        }

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

好吧,我們接著看下面的載入

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
            throws BeanDefinitionStoreException {
        try {  
            //此處把xml文件通過IO流讀入內(nèi)存并處理成Document類型,后續(xù)就可以通過dom操作了
            Document doc = doLoadDocument(inputSource, resource);
            return registerBeanDefinitions(doc, resource);
        }catch(各種catch){
                      ..........
                }
    }
@SuppressWarnings("deprecation")
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        //創(chuàng)建一個解析Document的BeanDefinitionReader
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
        documentReader.setEnvironment(getEnvironment());
        int countBefore = getRegistry().getBeanDefinitionCount();
        //利用DocumentReader注冊BeanDefinition
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        return getRegistry().getBeanDefinitionCount() - countBefore;
    }
 @Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        this.readerContext = readerContext;
        logger.debug("Loading bean definitions");
        Element root = doc.getDocumentElement();
        doRegisterBeanDefinitions(root);
    }
protected void doRegisterBeanDefinitions(Element root) {
        //實(shí)際上這里的root代表的是<beans>標(biāo)簽
        BeanDefinitionParserDelegate parent = this.delegate;
        this.delegate = createDelegate(getReaderContext(), root, parent);
        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)) {
                    return;
                }
            }
        }
        preProcessXml(root);
        parseBeanDefinitions(root, this.delegate);
        postProcessXml(root);

        this.delegate = parent;
    }

下面的方法利用迭代器迭代的把<beans>標(biāo)簽里的元素處理成內(nèi)存中的BeanDefinition

//真正解析bean標(biāo)簽的方法
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 {
            delegate.parseCustomElement(root);
        }
    }

下面的方法會創(chuàng)建一個BeanDefinitionHolder持有BeanDefinition及名字,別名數(shù)組

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        //持有beanName,BeanDefinition和Bean的別名
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                // 把beanName-BeanDefinition鍵值對放到private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);里面
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
            }
            catch (BeanDefinitionStoreException ex) {
                getReaderContext().error("Failed to register bean definition with name '" +
                        bdHolder.getBeanName() + "'", ele, ex);
            }
            // 發(fā)送注冊成功信號,告知容器已經(jīng)注冊好了所有Bean成BeanDefinition了
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }

下面這個方法是最終解析xml成BeanDefinition!??!

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
         //獲取BeanID
                String id = ele.getAttribute(ID_ATTRIBUTE);
              //獲取Bean的名字
        String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
          //獲取bean的所有別名
        List<String> aliases = new ArrayList<String>();
        if (StringUtils.hasLength(nameAttr)) {
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
            aliases.addAll(Arrays.asList(nameArr));
        }
        //如果bean沒有名字其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");
            }
        }

        if (containingBean == null) {
            checkNameUniqueness(beanName, aliases, ele);
        }

        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);
                        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);
        //返回BeanDefinationHolder
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        }
        return null;
    }

Ok以上代碼都執(zhí)行完BeanFactory的原材料算是準(zhǔn)備好了,BeanFactory可以拿著這些原材料制作Bean了


prepareBeanFactory方法解析:

該方法為BeanFactory工廠設(shè)置類加載器、bean創(chuàng)建監(jiān)聽器、初始化一些IOC容器自帶的必須要初始化的Bean

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        // Tell the internal bean factory to use the context's class loader etc.
        beanFactory.setBeanClassLoader(getClassLoader());
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
        beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

        // Configure the bean factory with context callbacks.
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
        beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
        beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
        beanFactory.ignoreDependencyInterface(EnvironmentAware.class);

        // BeanFactory interface not registered as resolvable type in a plain factory.
        // MessageSource registered (and found for autowiring) as a bean.
        beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
        beanFactory.registerResolvableDependency(ResourceLoader.class, this);
        beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
        beanFactory.registerResolvableDependency(ApplicationContext.class, this);

        // Detect a LoadTimeWeaver and prepare for weaving, if found.
        if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
            beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
            // Set a temporary ClassLoader for type matching.
            beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
        }

        // Register default environment beans.
        if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
        }
        if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
            beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
        }
    }

finishBeanFactoryInitialization(beanFactory)方法分析

該方法對那些非懶加載(spring默認(rèn))的Bean進(jìn)行預(yù)實(shí)例化

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // Initialize conversion service for this context.
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        // Stop using the temporary ClassLoader for type matching.
        beanFactory.setTempClassLoader(null);

        // Allow for caching all bean definition metadata, not expecting further changes.
        beanFactory.freezeConfiguration();

        // Instantiate all remaining (non-lazy-init) singletons.
        beanFactory.preInstantiateSingletons();
    }

//對配置lazy-init屬性Bean的預(yù)實(shí)例化  
public void preInstantiateSingletons() throws BeansException {  
       if (this.logger.isInfoEnabled()) {  
           this.logger.info("Pre-instantiating singletons in " + this);  
       }  
       synchronized (this.beanDefinitionMap) {  
           for (String beanName : this.beanDefinitionNames) {  
               //獲取指定名稱的Bean定義  
               RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);  
               //bean定義為非抽象,單例模式,非懶加載 
               if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {  
                   //如果指定名稱的bean是創(chuàng)建容器的Bean  
                   if (isFactoryBean(beanName)) {  
                   //FACTORY_BEAN_PREFIX=”&”,當(dāng)Bean名稱前面加”&”符號 時,獲取的是產(chǎn)生容器對象本身,而不是容器產(chǎn)生的Bean.  
                  //調(diào)用getBean方法,觸發(fā)容器對Bean實(shí)例化和依賴注入過程  
                       final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);  
                       //標(biāo)識是否需要預(yù)實(shí)例化  
                       boolean isEagerInit;  
                       if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {  
                           //一個匿名內(nèi)部類  
                           isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {  
                               public Boolean run() {  
                                   return ((SmartFactoryBean) factory).isEagerInit();  
                               }  
                           }, getAccessControlContext());  
                       }  
                       else {  
                           isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean) factory).isEagerInit();   
                       }  
                       if (isEagerInit) {  
                          //調(diào)用getBean方法,觸發(fā)容器對Bean實(shí)例化和依賴注入過程  
                           getBean(beanName);  
                       }  
                   }  
                   else {  
                        //調(diào)用getBean方法,觸發(fā)容器對Bean實(shí)例化和依賴注入過程  
                       getBean(beanName);  
                   }  
               }  
           }  
       }  
    }

下面這老長代碼我看著都害怕,這個方法是真正創(chuàng)建預(yù)實(shí)例化的Bean的方法,如果你嫌棄太長了,知道這句話也就差不多夠了。這個bean是純凈態(tài)無污染的bean哦。我們關(guān)注下面方法里的單例模式的bean的創(chuàng)建,和原型模式的bean的創(chuàng)建,直接看關(guān)鍵代碼(有注釋的)

@SuppressWarnings("unchecked")
    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 {
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                String nameToLookup = originalBeanName(name);
                if (args != null) {
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                }
                else {
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
            }

            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }
            try {
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                checkMergedBeanDefinition(mbd, beanName, args);
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dependsOnBean : dependsOn) {
                        if (isDependent(beanName, dependsOnBean)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
                        }
                        registerDependentBean(dependsOnBean, beanName);
                        getBean(dependsOnBean);
                    }
                }
                                //
                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()) {
                    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 '" + 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;
            }
        }
        if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
            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創(chuàng)建過程提取出來,下面方法的createBean就是真正創(chuàng)建Bean的地方

            if (mbd.isSingleton()) {
                    sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            try {  
                //真正創(chuàng)建Bean的地方,要把Bean和BeaNDefination信息傳給這個方法
                                return createBean(beanName, mbd, args);
                            }
                            catch (BeansException ex) {
                                destroySingleton(beanName);
                                throw ex;
                            }
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

下面的代碼就是真正執(zhí)行BeanDefination到Bean實(shí)例化的代碼,其中populateBean就是依賴注入發(fā)生的地方!?。。?/p>

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
        /**根據(jù)配置的Class信息創(chuàng)建一個實(shí)例包裹器,包裹器里包裹著一個實(shí)例化的bean,但此bean并沒有被賦值**/
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
    //獲取到這個沒有給屬性賦值的純凈Bean
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                mbd.postProcessed = true;
            }
        }
        //如果bean涉及到了循環(huán)引用,而且是單例的,而且是在創(chuàng)建過程中,則允許該bean提前曝光,我們下一章會講解Spring中的循環(huán)引用問題
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            ----------打印日志------------
            addSingletonFactory(beanName, new ObjectFactory<Object>() {
                @Override
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

        // 這里把剛剛創(chuàng)建好的bean進(jìn)行裝配,即使bean狀態(tài)變成成熟態(tài)!??!
        Object exposedObject = bean;
        try {
        //使Bean變成成熟態(tài)的真正方法,即依賴注入的真正發(fā)生地!?。。?!
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
        //對bean進(jìn)行后置處理器處理
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }
        -----------捕獲異常-------
        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()) {
                        ----------------拋出異常-------------
                    }
                }
            }
        }
        try {
            registerDisposableBeanIfNecessary(beanName, bean, mbd);
        }
        -------------捕獲異常-----------------
        return exposedObject;
    }

總結(jié)

經(jīng)過以上過程,Spring已經(jīng)啟動了一個全新的IOC容器,并把xml里配置的Bean從概念態(tài)轉(zhuǎn)變?yōu)檎嬲捎玫某墒鞈B(tài)并放到IOC容器里來管理了。我們可以通過getBean(“beanName”)來獲取Bean的成熟態(tài)實(shí)例!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容