程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Spring源代碼分析-XmlBeanFactory導讀

Spring源代碼分析-XmlBeanFactory導讀

編輯:關於JAVA

源代碼分析,是一件既痛苦又快樂的事情,看別人寫的代碼是通過的,但當你能夠看 明白的時候,相信快樂也會隨之而來,為了減少痛苦,更快的帶來快樂,在這裡希望通過 這篇文章對覺得困難的朋友有一個幫助。

首先來打開該類的代碼,我們將看到如下代碼:

Java代碼

public class XmlBeanFactory extends DefaultListableBeanFactory {
   private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
   public XmlBeanFactory(Resource resource) throws BeansException {
     this(resource, null);
   }
   public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
     super(parentBeanFactory);
     this.reader.loadBeanDefinitions(resource);
   }
}

這個類的代碼很簡單,一個成員對象加兩個構造函數,從這裡我們可以看出,最重要 的地方在於最後一個構造函數:

Java代碼

super(parentBeanFactory);
   this.reader.loadBeanDefinitions(resource);

第一句就是將父親工廠交給父類的構造函數,實際上最後也就是把父工廠保存到類的 parentBeanFactory成員對象中,這個對象是在AbstractBeanFactory抽象類中定義的,而 這個父工廠也會一直傳遞到該抽象類進行保存。第二句就是整個類中最重要的地方了,顧 名思義,它的目的是通過XmlBeanDefinitionReader這個XML的Reader從資源resource中( 也就是你的配置文件)讀取bean的定義。接下來我們打開XmlBeanDefinitionReader的 loadBeanDefinitions方法,我們可看到在這個方法裡代碼就一行,調用了一個同名不同 參的方法,而參數是EncodedResource的一個實例,這個類實際上是Resource的一個包裝 類,用來保存資源的Encode的,那接下來我們再看被調用的loadBeanDefinitions方法, 這個方法裡最主要的部分就是:

Java代碼

InputSource inputSource = new InputSource(inputStream);
         if (encodedResource.getEncoding() != null) {
           inputSource.setEncoding(encodedResource.getEncoding ());
         }
     return doLoadBeanDefinitions(inputSource, encodedResource.getResource());

這裡的目的是將資源包裝成一個InputSource,連同Resource作為參數傳遞到 doLoadBeanDefinitions方法

Java代碼

DocumentBuilderFactory factory = createDocumentBuilderFactory();
if (logger.isDebugEnabled()) {
         logger.debug("Using JAXP implementation [" + factory + "]");
}
DocumentBuilder builder = createDocumentBuilder(factory);
Document doc = builder.parse(inputSource);
return registerBeanDefinitions(doc, resource);

這個方法的目的一目了然,就是為了將資源解釋成為Document對象,然後調用 registerBeanDefinitions方法,這裡不做詳細解釋,不了解的話請去看看關於JAXP的介 紹。接下來我們打開registerBeanDefinitions方法:

Java代碼

public int registerBeanDefinitions(Document doc, Resource resource) throws BeansException {
     XmlBeanDefinitionParser parser =
         (XmlBeanDefinitionParser) BeanUtils.instantiateClass (this.parserClass);
     return parser.registerBeanDefinitions(this, doc, resource);
   }

這裡創建了一個XmlBeanDefinitionParser接口的實現,這個接口的具體類是 DefaultXmlBeanDefinitionParser,這個接口很簡單,只有registerBeanDefinitions一 個方法,這個方法的作用也很明了,就是用來注冊Bean的定義的,所以說類和方法的名字 一定要起得有意義,這樣可以讓人一看就大概了解其作用,減少了很多閱讀代碼的痛苦。 廢話不多說,我們打開DefaultXmlBeanDefinitionParser的registerBeanDefinitions方 法,這個類就是解釋XML配置文件的核心類了,打開registerBeanDefinitions方法後我們 看到如下代碼:

Java代碼

public int registerBeanDefinitions(BeanDefinitionReader reader, Document doc, Resource resource)
       throws BeanDefinitionStoreException {
     this.beanDefinitionReader = reader;
     this.resource = resource;
     logger.debug("Loading bean definitions");
     Element root = doc.getDocumentElement();
     //初始化根元素
     initDefaults(root);
     if (logger.isDebugEnabled()) {
       logger.debug("Default lazy init '" + getDefaultLazyInit() + "'");
       logger.debug("Default autowire '" + getDefaultAutowire() + "'");
       logger.debug("Default dependency check '" + getDefaultDependencyCheck() + "'");
     }
     preProcessXml(root);//一個空方法用於擴展
     int beanDefinitionCount = parseBeanDefinitions(root);//解釋配置的主 要方法
     if (logger.isDebugEnabled()) {
       logger.debug("Found " + beanDefinitionCount + " <bean> elements in " + resource);
     }
     postProcessXml(root); //一個空方法用於擴展
     return beanDefinitionCount;
   }

在這個方法當中,主要用於解釋定義的有兩個方法,一個是initDefaults,一個是 parseBeanDefinitions,第一個方法是用來解釋根元素的屬性的,例如lazy-init, autowire等,而parseBeanDefinitions就是用來解釋具體的bean定義了,方法代碼如下:

Java代碼

protected int parseBeanDefinitions(Element root) throws BeanDefinitionStoreException {
     NodeList nl = root.getChildNodes();
     int beanDefinitionCount = 0;
     for (int i = 0; i < nl.getLength(); i++) {
       Node node = nl.item(i);
       if (node instanceof Element) {
         Element ele = (Element) node;
         if (IMPORT_ELEMENT.equals(node.getNodeName())) {
           importBeanDefinitionResource(ele);
         }
         else if (ALIAS_ELEMENT.equals(node.getNodeName())) {
           String name = ele.getAttribute(NAME_ATTRIBUTE);
           String alias = ele.getAttribute(ALIAS_ATTRIBUTE);
           this.beanDefinitionReader.getBeanFactory ().registerAlias(name, alias);
         }
         else if (BEAN_ELEMENT.equals(node.getNodeName())) {
           beanDefinitionCount++;
           BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele, false);
           BeanDefinitionReaderUtils.registerBeanDefinition (bdHolder, this.beanDefinitionReader.getBeanFactory());
         }
       }
     }
     return beanDefinitionCount;
   }

其他標簽具體如何被解釋這裡就不多說,相信大家也能看得懂,這裡主要講一下解釋 bean的的處理,我們注意以下代碼:

Java代碼

else if (BEAN_ELEMENT.equals(node.getNodeName())) {
           beanDefinitionCount++;
           BeanDefinitionHolder bdHolder = parseBeanDefinitionElement(ele, false);
           BeanDefinitionReaderUtils.registerBeanDefinition (bdHolder, this.beanDefinitionReader.getBeanFactory());
         }

這裡是當碰到一個bean標簽的時候所進行的處理,也既是對bean的定義進行解釋,可 以看到parseBeanDefinitionElement方法的第一個參數就是bean則個元素,第二個參數表 示該bean是否為內置的bean,從這裡進行解釋的bean都不可能是內置的,所以這裡直接以 false為參數,打開parseBeanDefinitionElement方法,就可以看到這個方法裡就是對 bean的內部的解釋,也很簡單,也不多講了,呵呵(下班時間已經到了,所以就寫這麼多 了,基本的流程也就這樣,沒什麼特別難的地方。),對了,最後還有一點就是解釋完後 ,bean的定義將會被保存到beanFactory中,這個beanFactory的實現就是XmlBeanFactory 了,該beanFactory是在new的時候被傳遞到reader中的,就是該類中以下這行代碼:

Java代碼

private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);

好了,就這麼多了,本文只作為參考,只講解了如何加載bean定義這塊,只作為一個 參考,希望對其他朋友能有所幫助吧,因為時間匆忙,有錯漏的地方請指正。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved