1. 程式人生 > >spring源碼-bean之初始化-1

spring源碼-bean之初始化-1

name art array 形式 framework stat not found object 查看源

  一、spring的IOC控制反轉:控制反轉——Spring通過一種稱作控制反轉(IOC)的技術促進了松耦合。當應用了IOC,一個對象依賴的其它對象會通過被動的方式傳遞進來,而不是這個對象自己創建或者查找依賴對象。說白了就是原本需要手動去創建和管理的對象,現在交給容器了。在容器的基礎上,實現對象的控制。這個方式也很好的減少了開發者在框架上面的時間,更多關註點在業務邏輯上面。

  二、這表博客的主要目的是研究,bean容器的初始化,會在最基本的bean初始化作源碼的解析和分析。如何存在不妥當的地方,還請指出!

  三、BeanFactory是spring的核心,通過工廠的模式來創建和使用bean。

  四、我們都知道spring的bean初始化,依賴xml文件來實現的,所以這裏重點講解XmlBeanFactory的初始化過程。可能有人會問為什麽不是ApplicationContext,相對於ApplicationContext,XmlBeanFactory是基礎的bean初始化過程,後續我會單獨將ApplicationContext又做了哪些動作。

  五、源碼解讀

  1)創建xml配置文件spring-bean.xml(這裏省略User,,重點不在這裏)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.pinnet.customLabel.User"/> </beans>

  2)開始創建對象

package com.pinnet.bean;

import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; public class Test { public static void main(String[] args) { //讀取資源 Resource resource = new ClassPathResource("spring-bean.xml"); //初始化容器 new XmlBeanFactory(resource); } }

  3)初始化XmlBeanFactory

private final XmlBeanDefinitionReader reader;

    public XmlBeanFactory(Resource resource) throws BeansException {
        this(resource, (BeanFactory)null);
    }

    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
        super(parentBeanFactory);
        //用XmlBeanDefinitionReader,來進行加載
        this.reader = new XmlBeanDefinitionReader(this);
        //解析資源
        this.reader.loadBeanDefinitions(resource);
    }

  4)loadBeanDefinitions

public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
//包裝成EncodedResource
return this.loadBeanDefinitions(new EncodedResource(resource)); } 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 var6; try {
//轉換成InputStream流 InputStream inputStream
= encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } //進一步解析 var6 = 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 var6; } }

  5)doLoadBeanDefinitions

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
        try {
            int validationMode = this.getValidationModeForResource(resource);
//讀取xml為doc Document doc
= this.documentLoader.loadDocument(inputSource, this.getEntityResolver(), this.errorHandler, validationMode, this.isNamespaceAware());
//註冊BeanDefinition
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); } }

  6)registerBeanDefinitions

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        this.readerContext = readerContext;
        this.logger.debug("Loading bean definitions");
        Element root = doc.getDocumentElement();
        BeanDefinitionParserDelegate delegate = this.createHelper(readerContext, root);
     //此方法用於提供子類處理之用
this.preProcessXml(root); this.parseBeanDefinitions(root, delegate);
     //此方法用於提供子類處理之用
this.postProcessXml(root); }

  7)parseBeanDefinitions(這一部分就是解析過程了)

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)) {
              //默認標簽解析
this.parseDefaultElement(ele, delegate); } else {
              //自定義標簽解析(這裏後面講,這個也是非常重要的拓展功能)         delegate.parseCustomElement(ele); } } } }
else { delegate.parseCustomElement(root); } }

  8)parseDefaultElement(默認標簽解析,這裏關註bean)

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, "import")) {
            this.importBeanDefinitionResource(ele);
        } else if (delegate.nodeNameEquals(ele, "alias")) {
            this.processAliasRegistration(ele);
        } else if (delegate.nodeNameEquals(ele, "bean")) {
            this.processBeanDefinition(ele, delegate);
        }
    }

  9)processBeanDefinition

 protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
        //這裏主要是解析過程
        BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
        if (bdHolder != null) {
            bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
            try {
                //這裏註冊bean到beanDefinitionMap,後面會看到
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
            } catch (BeanDefinitionStoreException var5) {
                this.getReaderContext().error("Failed to register bean definition with name ‘" + bdHolder.getBeanName() + "‘", ele, var5);
            }
            this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }
    }

  a、parseBeanDefinitionElement

  public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
        return this.parseBeanDefinitionElement(ele, (BeanDefinition)null);
    }

    public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
        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((Collection)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) {
            //檢查id和別名是否重復
            this.checkNameUniqueness(beanName, aliases, ele);
        }

        //解析過程
        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
                        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); //將別名和beanName放入BeanDefinitionHolder return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } else { return null; } }

  parseBeanDefinitionElement(進一步解析過程,可以自己查看源碼,這裏不講解)

public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) {
        this.parseState.push(new BeanEntry(beanName));
        String className = null;
        if (ele.hasAttribute("class")) {
            className = ele.getAttribute("class").trim();
        }
        try {
            String parent = null;
            if (ele.hasAttribute("parent")) {
                parent = ele.getAttribute("parent");
            }
            //創建GenericBeanDefinition
            AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
            //解析bean上面的默認元素
            this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
            bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
            //meta
            this.parseMetaElements(ele, bd);
            //lookup-method
            this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
            //replaced-method
            this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
            //constructor-arg
            this.parseConstructorArgElements(ele, bd);
            //property
            this.parsePropertyElements(ele, bd);
            //qualifier
            this.parseQualifierElements(ele, bd);
            bd.setResource(this.readerContext.getResource());
            bd.setSource(this.extractSource(ele));
            //所有解析過後的元素全部放在AbstractBeanDefinition裏面
            AbstractBeanDefinition var8 = bd;
            return var8;
        } 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;
    }

  b、registerBeanDefinition(將AbstractBeanDefinition的相關數據放入beanDefinitionMap)

public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
        String beanName = definitionHolder.getBeanName();
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            String[] var7 = aliases;
            int var6 = aliases.length;

            for(int var5 = 0; var5 < var6; ++var5) {
                String aliase = var7[var5];
                registry.registerAlias(beanName, aliase);
            }
        }

    }
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");
        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition)beanDefinition).validate();
            } catch (BeanDefinitionValidationException var6) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var6);
            }
        }

        Map var3 = this.beanDefinitionMap;
        synchronized(this.beanDefinitionMap) {
            Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
            if (oldBeanDefinition != null) {
                if (!this.allowBeanDefinitionOverriding) {
                    throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean ‘" + beanName + "‘: There is already [" + oldBeanDefinition + "] bound.");
                }

                if (this.logger.isInfoEnabled()) {
                    this.logger.info("Overriding bean definition for bean ‘" + beanName + "‘: replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
                }
            } else {
                this.beanDefinitionNames.add(beanName);
                this.frozenBeanDefinitionNames = null;
            }
            //將beanName和beanDefinition形成鍵值對的形式,保存在Map中
            this.beanDefinitionMap.put(beanName, beanDefinition);
            this.resetBeanDefinition(beanName);
        }
    }

  六、好了,這就是源碼的實現過程,中間省略了很多的判定和實現過程。主要的流程,基本上就是這樣。這裏重點註意幾個點,也是對流程的梳理

  1)初始化XmlBeanFactory,需要註意XmlBeanDefinitionReader:這是整個解讀過程的關鍵

  2)然後就是字符集包裝,然後形成流EncodedResource、inputSource

  3)解析xml,基本上是通過spring的DefaultDocumentLoader實現的,通過對Document文檔的解析來實現標簽和元素的解析

  4)判斷是否是默認標簽是通過xml的Namespace來實現的,默認Namespace的讀取目錄是通過DefaultNamespaceHandlerResolver來實現的,也就是讀取spring.handlers和spring.schemas,後續會講到這兩個文件的作用

  public boolean isDefaultNamespace(String namespaceUri) {
        return !StringUtils.hasLength(namespaceUri) || "http://www.springframework.org/schema/beans".equals(namespaceUri);
    }
  protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
        return new DefaultNamespaceHandlerResolver(this.getResourceLoader().getClassLoader());
    }

  spring.handlers

http\://www.springframework.org/schema/p=org.springframework.beans.factory.xml.SimplePropertyNamespaceHandler
http\://www.springframework.org/schema/util=org.springframework.beans.factory.xml.UtilNamespaceHandler

  spring.schemas

http\://www.springframework.org/schema/beans/spring-beans-2.0.xsd=org/springframework/beans/factory/xml/spring-beans-2.0.xsd
http\://www.springframework.org/schema/beans/spring-beans-2.5.xsd=org/springframework/beans/factory/xml/spring-beans-2.5.xsd
http\://www.springframework.org/schema/beans/spring-beans-3.0.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
http\://www.springframework.org/schema/beans/spring-beans.xsd=org/springframework/beans/factory/xml/spring-beans-3.0.xsd
http\://www.springframework.org/schema/tool/spring-tool-2.0.xsd=org/springframework/beans/factory/xml/spring-tool-2.0.xsd
http\://www.springframework.org/schema/tool/spring-tool-2.5.xsd=org/springframework/beans/factory/xml/spring-tool-2.5.xsd
http\://www.springframework.org/schema/tool/spring-tool-3.0.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
http\://www.springframework.org/schema/tool/spring-tool.xsd=org/springframework/beans/factory/xml/spring-tool-3.0.xsd
http\://www.springframework.org/schema/util/spring-util-2.0.xsd=org/springframework/beans/factory/xml/spring-util-2.0.xsd
http\://www.springframework.org/schema/util/spring-util-2.5.xsd=org/springframework/beans/factory/xml/spring-util-2.5.xsd
http\://www.springframework.org/schema/util/spring-util-3.0.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd
http\://www.springframework.org/schema/util/spring-util.xsd=org/springframework/beans/factory/xml/spring-util-3.0.xsd

  5)解析bean標簽,是生產一個GenericBeanDefinition這個類是繼承AbstractBeanDefinition生產BeanDefinition的過程其實就是講標簽裏面的元素進行解析放入的過程

  6)註冊的過程是放在DefaultListableBeanFactory裏面的beanDefinitionMap,是不是有點奇怪過程並沒有DefaultListableBeanFactory。在源碼的9)中使用了BeanDefinitionRegistry ,而這個BeanDefinitionRegistry 也是我們最開始使用的XmlBeanFactory,但是XmlBeanFactory,並沒有太多的實現。看來一個結構:

技術分享圖片

  其實最開始調用XmlBeanFactory的時候就已經使用了DefaultListableBeanFactory,值不夠是繼承關系而已。所以這裏基本上所有的數據都在DefaultListableBeanFactory裏面了

  7)最後解析過程就到這裏,主要數據全部在DefaultListableBeanFactorybeanDefinitionMap裏面。

  8)註意一點,別名的加載過程也很重要,這裏不多介紹,多想法自己查看源碼

  七、容器的初始化基本上就是這樣了,主要是梳理流程和spring在IOC的控制中做了什麽。

spring源碼-bean之初始化-1