<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

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

    常用鏈接

    留言簿(19)

    隨筆檔案(115)

    文章檔案(4)

    新聞檔案(1)

    成員連接

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

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

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

       首先來打開該類的代碼,我們將看到如下代碼:
    以下內容為程序代碼:

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

    }


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

    以下內容為程序代碼:

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


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

    以下內容為程序代碼:

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


       這里的目的是將資源包裝成一個InputSource,連同Resource作為參數傳遞到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]

       這個方法的目的一目了然,就是為了將資源解釋成為Document對象,然后調用registerBeanDefinitions方法,這里不做詳細解釋,不了解的話請去看看關于JAXP的介紹。接下來我們打開registerBeanDefinitions方法:
    以下內容為程序代碼:

       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方法后我們看到如下代碼:
    以下內容為程序代碼:

       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定義了,方法代碼如下:
    以下內容為程序代碼:

       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的的處理,我們注意以下代碼:
    以下內容為程序代碼:

                   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中的,就是該類中以下這行代碼:
    以下內容為程序代碼:

       private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);


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

     (本文作者:easyjf開源 calmness)

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

    FeedBack:
    # re: spring源碼分析-XmlBeanFactory導讀  2007-04-30 14:38 BeanSoft
    開源不開架構文檔和系統手冊以及設計文檔, 所以, 現在的大多數開源, 充其量只能算是能閱讀源碼而已. 就是給了代碼, 也不容易看懂, 例如現在的 Eclipse, 代碼已經再幾大廠商的努力下寫的外人看不懂. 再例如 JDK 源碼, C 寫的, 給了也看不懂.

    正在看 Spring, 支持一下.  回復  更多評論
      

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 激情内射亚洲一区二区三区| 亚洲熟妇av一区二区三区| 精品亚洲国产成AV人片传媒| 在线观看黄片免费入口不卡| 亚洲日产无码中文字幕| a毛片免费全部播放完整成| 国产AV无码专区亚洲AV男同| 国产一区二区免费| 在线观看免费a∨网站| 亚洲免费视频在线观看| 久久久久久久久久国产精品免费| 免费国产成人高清在线观看麻豆| 亚洲国产成人久久综合| 一个人免费观看视频www| 亚洲人成网站18禁止| 国产三级免费电影| 中文无码日韩欧免费视频| 国产极品粉嫩泬免费观看 | 三级网站在线免费观看| 中文字幕精品亚洲无线码二区| 亚洲AV无码专区国产乱码不卡 | 最近最新中文字幕完整版免费高清| 久久精品国产亚洲综合色| 日本xxxx色视频在线观看免费| 91亚洲国产成人久久精品| 国产免费久久精品| 精品一卡2卡三卡4卡免费视频| 亚洲欧洲日产国码二区首页| 99久久99久久精品免费观看| 亚洲人成图片网站| 久久精品国产亚洲7777| 免费无遮挡无码永久视频| 国产成人亚洲精品电影| 国产成人亚洲综合无码精品 | 国产精品亚洲精品| 国产啪精品视频网免费| 羞羞视频在线观看免费| 亚洲国产精品成人AV无码久久综合影院| 亚洲精品无码久久久久秋霞| 国产综合亚洲专区在线| 中文字幕影片免费在线观看|