Spring技術內幕筆記(1)——IOC容器初始化過程

IOC容器的初始化是由refresh()方法來啓動的,這個方法標誌着IOC容器的正式啓動。
IOC容器初始化的過程
Resource定位過程:把容器比做水桶,類似於容器查找數據,提着水桶尋找水源;
BeanDefinition載入:容器中的主要的數據結構,類似於水;
**向IOC容器中註冊這些BeanDefinition:**把水倒入水桶中;

在這個註冊的過程中,一般不包含Bean依賴注入的實現。在SpringIOC設計過程中,載入和依賴注入是兩個過程。依賴注入發生在第一次獲取bean的時候。

BeanDefinition的Resource定位

ClassPathResource res = new ClassPathResource(“beans.xml”);

org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory

protected final void refreshBeanFactory() throws BeansException {
		//在這裏進行判斷,如果已經有了beanFactory,則銷燬並關閉
        if (this.hasBeanFactory()) {
            this.destroyBeans();
            this.closeBeanFactory();
        }

        try {
		//創建DefaultListableBeanFactory
            DefaultListableBeanFactory beanFactory = this.createBeanFactory();
            beanFactory.setSerializationId(this.getId());
            this.customizeBeanFactory(beanFactory);
			//調用loadBeanDefinitions再載入BeanDefinition信息
            this.loadBeanDefinitions(beanFactory);
            synchronized(this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        } catch (IOException var5) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
        }
    }

org.springframework.core.io.DefaultResourceLoader#getResource

   public Resource getResource(String location) {
        Assert.notNull(location, "Location must not be null");
		//這裏處理classpath:開頭的路徑
        if (location.startsWith("classpath:")) {
            return new ClassPathResource(location.substring("classpath:".length()), this.getClassLoader());
        } else {
            try {
			//這裏處理URL表示的Resource位置
                URL url = new URL(location);
                return new UrlResource(url);
            } catch (MalformedURLException var3) {
			//如果兩個都不是,則通過下面的方法獲取
                return this.getResourceByPath(location);
            }
        }
    }

org.springframework.context.support.FileSystemXmlApplicationContext#FileSystemXmlApplicationContext(java.lang.String[], boolean, org.springframework.context.ApplicationContext)

 public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
        super(parent);
        this.setConfigLocations(configLocations);
		//這裏調用容器的refresh,是載入BeanDefinition的入口
        if (refresh) {
            this.refresh();
        }

    }

BeanDefinition的載入和解析

在這裏插入圖片描述

org.springframework.context.support.AbstractApplicationContext#refresh

public void refresh() throws BeansException, IllegalStateException {
        synchronized(this.startupShutdownMonitor) {
            this.prepareRefresh();
			//這裏是在子類中啓動refreshBeanFactory的地方
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
			
			//準備在這個上下文環境中使用的BeanFactory
            this.prepareBeanFactory(beanFactory);

            try {
			//設置BeanFactory的後置處理器
                this.postProcessBeanFactory(beanFactory);
				//調用BeanFactory的後置處理器,這些後處理器是在Bean定義中向容器註冊的
                this.invokeBeanFactoryPostProcessors(beanFactory);
				//註冊Bean的後處理器,在Bean創建過程中調用;
                this.registerBeanPostProcessors(beanFactory);
				//對上下文中的消息源進行初始化
                this.initMessageSource();
				//初始化上下文中的事件機制
                this.initApplicationEventMulticaster();
				//初始化其他特殊的Bean
                this.onRefresh();
				//檢查監聽Bean並且將這些Bean向容器註冊
                this.registerListeners();
				//實例化所有的non-lazy-inti單件
                this.finishBeanFactoryInitialization(beanFactory);
				//發佈容器事件,結束Refresh過程
                this.finishRefresh();
            } catch (BeansException var5) {
			//爲防止Bean資源佔用,在異常處理中,銷燬已經生成的bean
                this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);
                this.destroyBeans();
				//重置active標誌
                this.cancelRefresh(var5);
                throw var5;
            }

        }
    }

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.support.EncodedResource)

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
//創建beanDefinitionReader,並且通過回調設置到BeanFactory中
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
    beanDefinitionReader.setEnvironment(this.getEnvironment());
	//beanDefinitionReader配置ResourceLoader,因爲DefaultResourceLoader是父類,可以直接使用this
    beanDefinitionReader.setResourceLoader(this);
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
	//這裏啓動bean定義信息載入過程
    this.initBeanDefinitionReader(beanDefinitionReader);
    this.loadBeanDefinitions(beanDefinitionReader);
}

org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.xml.XmlBeanDefinitionReader)

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
//以Resource形式獲取配置文件的資源位置
    Resource[] configResources = this.getConfigResources();
    if (configResources != null) {
        reader.loadBeanDefinitions(configResources);
    }
//以String數組的形式獲取配置文件的資源位置
    String[] configLocations = this.getConfigLocations();
    if (configLocations != null) {
        reader.loadBeanDefinitions(configLocations);
    }

}

org.springframework.beans.factory.support.AbstractBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource…)
public int loadBeanDefinitions(Resource… resources) throws BeanDefinitionStoreException {

    Assert.notNull(resources, "Resource array must not be null");
    int counter = 0;
    Resource[] arr$ = resources;
    int len$ = resources.length;
	//遍歷Resource中包含的BeanDefinition信息
    for(int i$ = 0; i$ < len$; ++i$) {
        Resource resource = arr$[i$];
        counter += this.loadBeanDefinitions((Resource)resource);
    }

    return counter;
}

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.support.EncodedResource)

//這裏載入XML形式的BeanDefinition的地方
    public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        Assert.notNull(encodedResource, "EncodedResource must not be null");
        if (this.logger.isInfoEnabled()) {
            this.logger.info("Loading XML bean definitions from " + encodedResource.getResource());
        }

        Set<EncodedResource> currentResources = (Set)this.resourcesCurrentlyBeingLoaded.get();
        if (currentResources == null) {
            currentResources = new HashSet(4);
            this.resourcesCurrentlyBeingLoaded.set(currentResources);
        }

        if (!((Set)currentResources).add(encodedResource)) {
            throw new BeanDefinitionStoreException("Detected cyclic loading of " + encodedResource + " - check your import definitions!");
        } else {
            int var5;
			//這裏得到XML文件,並得到IO的INPUTSOURCE準備進行讀取
            try {
                InputStream inputStream = encodedResource.getResource().getInputStream();

                try {
                    InputSource inputSource = new InputSource(inputStream);
                    if (encodedResource.getEncoding() != null) {
                        inputSource.setEncoding(encodedResource.getEncoding());
                    }

                    var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
                } finally {
                    inputStream.close();
                }
            } catch (IOException var15) {
                throw new BeanDefinitionStoreException("IOException parsing XML document from " + encodedResource.getResource(), var15);
            } finally {
                ((Set)currentResources).remove(encodedResource);
                if (((Set)currentResources).isEmpty()) {
                    this.resourcesCurrentlyBeingLoaded.remove();
                }

            }

            return var5;
        }
    }

BeanDefinition在IOC容器中的註冊

在這裏插入圖片描述

org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions

 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
        try {
            int validationMode = this.getValidationModeForResource(resource);
			//這裏取得XML文件的DOC對象,這個解析過程是由Document完成的。
            Document doc = this.documentLoader.loadDocument(inputSource, this.getEntityResolver(), this.errorHandler, validationMode, this.isNamespaceAware());
			//這裏啓動的是對BeanDefinition解析的詳細過程,這個解析會使用到spring的Bean配置規則
            return this.registerBeanDefinitions(doc, resource);
        } catch (BeanDefinitionStoreException var5) {
            throw var5;
        } catch (SAXParseException var6) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + var6.getLineNumber() + " in XML document from " + resource + " is invalid", var6);
        } catch (SAXException var7) {
            throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", var7);
        } catch (ParserConfigurationException var8) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, var8);
        } catch (IOException var9) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, var9);
        } catch (Throwable var10) {
            throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, var10);
        }
    }

org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processBeanDefinition

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
	//BeanDefinitionHolder是BeanDefinition的封裝類,封裝了BeanDefinition、Bean的名字和別名,用它來向IOC容器註冊;
	//得到BeanDefinitionHolder表明通過了sping規則解析得到的
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);

            try {
			//這裏是向IOC容器註冊解析得到的BeanDefinition的地方
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
            } catch (BeanDefinitionStoreException var5) {
                this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
            }

			//在BeanDefinition向ICO容器註冊後,發送消息
            this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }

    }

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)

 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
	//這裏獲取<bean>元素定義的id、name和aliase屬性的值
        String id = ele.getAttribute("id");
        String nameAttr = ele.getAttribute("name");
        List<String> aliases = new ArrayList();
        if (StringUtils.hasLength(nameAttr)) {
            String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
            aliases.addAll(Arrays.asList(nameArr));
        }

        String beanName = id;
        if (!StringUtils.hasText(id) && !aliases.isEmpty()) {
            beanName = (String)aliases.remove(0);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
            }
        }

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

		//這個方法是對Bean的詳細解析
        AbstractBeanDefinition beanDefinition = this.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 (this.logger.isDebugEnabled()) {
                        this.logger.debug("Neither XML 'id' nor 'name' specified - using generated bean name [" + beanName + "]");
                    }
                } catch (Exception var9) {
                    this.error(var9.getMessage(), ele);
                    return null;
                }
            }

            String[] aliasesArray = StringUtils.toStringArray(aliases);
            return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
        } else {
            return null;
        }
    }

org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, java.lang.String, org.springframework.beans.factory.config.BeanDefinition)

public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
        this.parseState.push(new BeanEntry(beanName));
		//這是隻是獲取bean定義中的class名字,然後載入在BeanDefinition中,只是記錄,不涉及實例化過程,實例化是依賴注入時進行的
        String className = null;
        if (ele.hasAttribute("class")) {
            className = ele.getAttribute("class").trim();
        }

        try {
            String parent = null;
            if (ele.hasAttribute("parent")) {
                parent = ele.getAttribute("parent");
            }
			//這裏生成需要的BeanDefinition對象,爲Bean定義信息的載入做準備
            AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
			//這裏對當前的bean元素進行屬性解析,並設置describe信息
            this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);		
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
			//這裏是對bean元素的信息進行解析的地方
            this.parseMetaElements(ele, bd);
            this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
			//解析bean的構造函數設置
            this.parseConstructorArgElements(ele, bd);
			//解析bean的property設置
            this.parsePropertyElements(ele, bd);
            this.parseQualifierElements(ele, bd);
            bd.setResource(this.readerContext.getResource());
            bd.setSource(this.extractSource(ele));
            AbstractBeanDefinition var7 = bd;
            return var7;
			//經常看到的異常信息
        } catch (ClassNotFoundException var13) {
            this.error("Bean class [" + className + "] not found", ele, var13);
        } catch (NoClassDefFoundError var14) {
            this.error("Class that bean class [" + className + "] depends on not found", ele, var14);
        } catch (Throwable var15) {
            this.error("Unexpected failure during bean definition parsing", ele, var15);
        } finally {
            this.parseState.pop();
        }

        return null;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章