隨筆 - 115  文章 - 481  trackbacks - 0
          <2007年4月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          常用鏈接

          留言簿(19)

          隨筆檔案(115)

          文章檔案(4)

          新聞檔案(1)

          成員連接

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          源代碼分析,是一件既痛苦又快樂(lè)的事情,看別人寫(xiě)的代碼是通過(guò)的,但當(dāng)你能夠看明白的時(shí)候,相信快樂(lè)也會(huì)隨之而來(lái),為了減少痛苦,更快的帶來(lái)快樂(lè),在這里希望通過(guò)這篇文章對(duì)覺(jué)得困難的朋友有一個(gè)幫助。

             本文以spring框架的XmlBeanFactory為入手點(diǎn)進(jìn)行分析,希望能夠以盡量簡(jiǎn)潔明了的方式給予有需要的朋友一定的幫助。

             首先來(lái)打開(kāi)該類的代碼,我們將看到如下代碼:
          以下內(nèi)容為程序代碼:

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

          }


             這個(gè)類的代碼很簡(jiǎn)單,一個(gè)成員對(duì)象加兩個(gè)構(gòu)造函數(shù),從這里我們可以看出,最重要的地方在于最后一個(gè)構(gòu)造函數(shù):

          以下內(nèi)容為程序代碼:

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


             第一句就是將父親工廠交給父類的構(gòu)造函數(shù),實(shí)際上最后也就是把父工廠保存到類的parentBeanFactory成員對(duì)象中,這個(gè)對(duì)象是在AbstractBeanFactory抽象類中定義的,而這個(gè)父工廠也會(huì)一直傳遞到該抽象類進(jìn)行保存。第二句就是整個(gè)類中最重要的地方了,顧名思義,它的目的是通過(guò)XmlBeanDefinitionReader這個(gè)XML的Reader從資源resource中(也就是你的配置文件)讀取bean的定義。接下來(lái)我們打開(kāi)XmlBeanDefinitionReader的loadBeanDefinitions方法,我們可看到在這個(gè)方法里代碼就一行,調(diào)用了一個(gè)同名不同參的方法,而參數(shù)是EncodedResource的一個(gè)實(shí)例,這個(gè)類實(shí)際上是Resource的一個(gè)包裝類,用來(lái)保存資源的Encode的,那接下來(lái)我們?cè)倏幢徽{(diào)用的loadBeanDefinitions方法,這個(gè)方法里最主要的部分就是:

          以下內(nèi)容為程序代碼:

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


             這里的目的是將資源包裝成一個(gè)InputSource,連同Resource作為參數(shù)傳遞到doLoadBeanDefinitions方法

          [code]
                     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);
          [/code]

             這個(gè)方法的目的一目了然,就是為了將資源解釋成為Document對(duì)象,然后調(diào)用registerBeanDefinitions方法,這里不做詳細(xì)解釋,不了解的話請(qǐng)去看看關(guān)于JAXP的介紹。接下來(lái)我們打開(kāi)registerBeanDefinitions方法:
          以下內(nèi)容為程序代碼:

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


             這里創(chuàng)建了一個(gè)XmlBeanDefinitionParser接口的實(shí)現(xiàn),這個(gè)接口的具體類是DefaultXmlBeanDefinitionParser,這個(gè)接口很簡(jiǎn)單,只有registerBeanDefinitions一個(gè)方法,這個(gè)方法的作用也很明了,就是用來(lái)注冊(cè)Bean的定義的,所以說(shuō)類和方法的名字一定要起得有意義,這樣可以讓人一看就大概了解其作用,減少了很多閱讀代碼的痛苦。廢話不多說(shuō),我們打開(kāi)DefaultXmlBeanDefinitionParser的registerBeanDefinitions方法,這個(gè)類就是解釋XML配置文件的核心類了,打開(kāi)registerBeanDefinitions方法后我們看到如下代碼:
          以下內(nèi)容為程序代碼:

             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);//一個(gè)空方法用于擴(kuò)展
                 int beanDefinitionCount = parseBeanDefinitions(root);//解釋配置的主要方法
                 if (logger.isDebugEnabled()) {
                     logger.debug("Found " + beanDefinitionCount + " <bean> elements in " + resource);
                 }
                 postProcessXml(root); //一個(gè)空方法用于擴(kuò)展

                 return beanDefinitionCount;
             }


             在這個(gè)方法當(dāng)中,主要用于解釋定義的有兩個(gè)方法,一個(gè)是initDefaults,一個(gè)是parseBeanDefinitions,第一個(gè)方法是用來(lái)解釋根元素的屬性的,例如lazy-init, autowire等,而parseBeanDefinitions就是用來(lái)解釋具體的bean定義了,方法代碼如下:
          以下內(nèi)容為程序代碼:

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


             其他標(biāo)簽具體如何被解釋這里就不多說(shuō),相信大家也能看得懂,這里主要講一下解釋bean的的處理,我們注意以下代碼:
          以下內(nèi)容為程序代碼:

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

             這里是當(dāng)碰到一個(gè)bean標(biāo)簽的時(shí)候所進(jìn)行的處理,也既是對(duì)bean的定義進(jìn)行解釋,可以看到parseBeanDefinitionElement方法的第一個(gè)參數(shù)就是bean則個(gè)元素,第二個(gè)參數(shù)表示該bean是否為內(nèi)置的bean,從這里進(jìn)行解釋的bean都不可能是內(nèi)置的,所以這里直接以false為參數(shù),打開(kāi)parseBeanDefinitionElement方法,就可以看到這個(gè)方法里就是對(duì)bean的內(nèi)部的解釋,也很簡(jiǎn)單,也不多講了,呵呵(下班時(shí)間已經(jīng)到了,所以就寫(xiě)這么多了,基本的流程也就這樣,沒(méi)什么特別難的地方。),對(duì)了,最后還有一點(diǎn)就是解釋完后,bean的定義將會(huì)被保存到beanFactory中,這個(gè)beanFactory的實(shí)現(xiàn)就是XmlBeanFactory了,該beanFactory是在new的時(shí)候被傳遞到reader中的,就是該類中以下這行代碼:
          以下內(nèi)容為程序代碼:

             private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);


             好了,就這么多了,本文只作為參考,只講解了如何加載bean定義這塊,只作為一個(gè)參考,希望對(duì)其他朋友能有所幫助吧,因?yàn)闀r(shí)間匆忙,有錯(cuò)漏的地方請(qǐng)指正。

           (本文作者:easyjf開(kāi)源 calmness)

          posted on 2007-04-29 09:36 簡(jiǎn)易java框架 閱讀(2223) 評(píng)論(1)  編輯  收藏

          FeedBack:
          # re: spring源碼分析-XmlBeanFactory導(dǎo)讀  2007-04-30 14:38 BeanSoft
          開(kāi)源不開(kāi)架構(gòu)文檔和系統(tǒng)手冊(cè)以及設(shè)計(jì)文檔, 所以, 現(xiàn)在的大多數(shù)開(kāi)源, 充其量只能算是能閱讀源碼而已. 就是給了代碼, 也不容易看懂, 例如現(xiàn)在的 Eclipse, 代碼已經(jīng)再幾大廠商的努力下寫(xiě)的外人看不懂. 再例如 JDK 源碼, C 寫(xiě)的, 給了也看不懂.

          正在看 Spring, 支持一下.  回復(fù)  更多評(píng)論
            

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 青神县| 宜州市| 奉节县| 万安县| 军事| 长葛市| 竹山县| 綦江县| 武山县| 郎溪县| 华容县| 沁阳市| 望江县| 乌拉特后旗| 前郭尔| 喜德县| 奉新县| 普兰店市| 迭部县| 微山县| 南开区| 珠海市| 新疆| 卢龙县| 临清市| 乌什县| 隆化县| 云霄县| 郸城县| 马关县| 镇原县| 沙湾县| 大兴区| 屏东县| 张掖市| 德保县| 五莲县| 海宁市| 牙克石市| 繁峙县| 清涧县|