亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

springIOC源碼分析(2)

2019-11-14 15:24:53
字體:
來源:轉載
供稿:網友

refresh這個方法包含了整個BeanFactory初始化的過程,定位資源由obtainFreshBeanFactory()來完成,

[java] view plaincopy
 
  1. PRotected ConfigurableListableBeanFactory obtainFreshBeanFactory() {  
  2.         refreshBeanFactory();  
  3.         ConfigurableListableBeanFactory beanFactory = getBeanFactory();  
  4.         if (logger.isDebugEnabled()) {  
  5.             logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);  
  6.         }  
  7.         return beanFactory;  
  8.     }  

         可以看到其調用了refreshBeanFactory(),refreshBeanFactory()在這個類中是抽象方法,其實現在AbstractRefreshableapplicationContext中。

[java] view plaincopy
 
  1. protected final void refreshBeanFactory() throws BeansException {  
  2.         if (hasBeanFactory()) {  
  3.             destroyBeans();  
  4.             closeBeanFactory();  
  5.         }  
  6.         try {  
  7.             DefaultListableBeanFactory beanFactory = createBeanFactory();  
  8.             beanFactory.setSerializationId(getId());  
  9.             customizeBeanFactory(beanFactory);  
  10.             loadBeanDefinitions(beanFactory);  
  11.             synchronized (this.beanFactoryMonitor) {  
  12.                 this.beanFactory = beanFactory;  
  13.             }  
  14.         }  
  15.         catch (IOException ex) {  
  16.             ……  
  17.         }  
  18. }  

          在這個方法中,先判斷BeanFactory是否存在,如果存在則先銷毀beans并關閉beanFactory,接著創建DefaultListableBeanFactory,并調用loadBeanDefinitions(beanFactory)裝載bean定義。loadBeanDefinitions方法同樣是抽象方法,是由其子類實現的,也即在AbstractxmlApplicationContext中。

[java] view plaincopy
 
  1. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {    
  2.    <span style="color:#33ff33;"> // 這里使用XMLBeanDefinitionReader來載入bean定義信息的XML文件</span>    
  3.     XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);    
  4.     
  5.     <span style="color:#33ff33;">//這里配置reader的環境,其中ResourceLoader是我們用來定位bean定義信息資源位置的</span>    
  6.  <span style="color:#33ff33;">   //因為上下文本身實現了ResourceLoader接口,所以可以直接把上下文作為ResourceLoader傳遞給XmlBeanDefinitionReader </span>   
  7.     beanDefinitionReader.setResourceLoader(this);    
  8.     beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));    
  9.     
  10.     initBeanDefinitionReader(beanDefinitionReader);    
  11.     <span style="color:#33ff33;">//這里轉到定義好的XmlBeanDefinitionReader中對載入bean信息進行處理</span>    
  12.     loadBeanDefinitions(beanDefinitionReader);    
  13. }    

          接著我們轉到beanDefinitionReader中進行處理

[java] view plaincopy
 
  1. protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {    
  2.     Resource[] configResources = getConfigResources();    
  3.     if (configResources != null) {    
  4.       <span style="color:#33ff33;">  //調用XmlBeanDefinitionReader來載入bean定義信息。</span>    
  5.         reader.loadBeanDefinitions(configResources);    
  6.     }    
  7.     String[] configLocations = getConfigLocations();    
  8.     if (configLocations != null) {    
  9.         reader.loadBeanDefinitions(configLocations);    
  10.     }    
  11. }    

         可以到org.springframework.beans.factory.support看一下BeanDefinitionReader的結構

        在其抽象父類AbstractBeanDefinitionReader中定義了載入過程

 

[java] view plaincopy
 
  1. public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {    
  2.    <span style="color:#33ff33;"> //這里得到當前定義的ResourceLoader,默認的我們使用DefaultResourceLoader </span>   
  3.     ResourceLoader resourceLoader = getResourceLoader();    
  4.     <span style="color:#33ff33;">//如果沒有找到我們需要的ResourceLoader,直接拋出異常</span>    
  5.     if (resourceLoader instanceof ResourcePatternResolver) {    
  6.         <span style="color:#33ff33;">// 這里處理我們在定義位置時使用的各種pattern,需要 ResourcePatternResolver來完成</span>    
  7.         try {    
  8.             Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);    
  9.             int loadCount = loadBeanDefinitions(resources);    
  10.             return loadCount;    
  11.         }    
  12.         ........    
  13.     }    
  14.     else {    
  15.         <span style="color:#33ff33;">// 這里通過ResourceLoader來完成位置定位</span>    
  16.         Resource resource = resourceLoader.getResource(location);    
  17.             <span style="color:#33ff33;"> // 這里已經把一個位置定義轉化為Resource接口,可以供XmlBeanDefinitionReader來使用了</span>    
  18.         int loadCount = loadBeanDefinitions(resource);    
  19.         return loadCount;    
  20.     }    
  21. }   



 


        看到第8、16行,結合上面的ResourceLoader與ApplicationContext的繼承關系圖,可以知道此時調用的是DefaultResourceLoader中的getSource()方法定位Resource,因為ClassPathXmlApplicationContext本身就是DefaultResourceLoader的實現類,所以此時又回到了ClassPathXmlApplicationContext中來。

 

        繼續回到XmlBeanDefinitionReader的loadBeanDefinitions(Resource …)方法看得到代表bean文件的資源定義以后的載入過程。

[java] view plaincopy
 
  1. public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {    
  2.     .......    
  3.     try {    
  4.         <span style="color:#33ff33;">//這里通過Resource得到InputStream的IO流</span>    
  5.         InputStream inputStream = encodedResource.getResource().getInputStream();    
  6.         try {    
  7.            <span style="color:#33ff33;"> //從InputStream中得到XML的解析源</span>    
  8.             InputSource inputSource = new InputSource(inputStream);    
  9.             if (encodedResource.getEncoding() != null) {    
  10.                 inputSource.setEncoding(encodedResource.getEncoding());    
  11.             }    
  12.             <span style="color:#33ff33;">//這里是具體的解析和注冊過程</span>    
  13.             return doLoadBeanDefinitions(inputSource, encodedResource.getResource());    
  14.         }    
  15.         finally {    
  16.             <span style="BACKGROUND-COLOR: #33ff33">//關閉從Resource中得到的IO流</span>    
  17.             inputStream.close();    
  18.         }    
  19.     }    
  20.        .........    
  21. }    
  22.     
  23. protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)    
  24.         throws BeanDefinitionStoreException {    
  25.     try {    
  26.         int validationMode = getValidationModeForResource(resource);    
  27.         <span style="color:#33ff33;">//通過解析得到DOM,然后完成bean在IOC容器中的注冊</span>    
  28.         Document doc = this.documentLoader.loadDocument(    
  29.                 inputSource, this.entityResolver, this.errorHandler, validationMode, this.namespaceAware);    
  30.         return registerBeanDefinitions(doc, resource);    
  31.     }    
  32. .......    
  33. }  

        在doLoadBeanDefinitions(…)先把定義文件解析為DOM對象,然后進行具體的注冊過程。

[java] view plaincopy
 
  1. public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {  
  2.         <span style="color:#33ff33;">//具體的注冊過程,首先得到XmlBeanDefinitionDocumentReader來處理xml的bean定義文件</span>  
  3.         BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();  
  4.         documentReader.setEnvironment(this.getEnvironment());  
  5.         int countBefore = getRegistry().getBeanDefinitionCount();  
  6.         <span style="color:#33ff33;">//調用注冊方法</span>  
  7.                      documentReader.registerBeanDefinitions(doc,createReaderContext(resource));  
  8.              return getRegistry().getBeanDefinitionCount() - countBefore;  
  9. }  
  10. <p> </p>  

 

        具體的過程在BeanDefinitionDocumentReader中完成,在DefaultBeanDefinitionDocumentReader的方法中完成bean定義文件的解析和IOC容器中bean的初始化。

[java] view plaincopy
 
  1. public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {  
  2.         this.readerContext = readerContext;  
  3.   
  4.         logger.debug("Loading bean definitions");  
  5.         Element root = doc.getDocumentElement();  
  6.   
  7.         doRegisterBeanDefinitions(root);  
  8. }  

 

[java] view plaincopy
 
  1. protected void doRegisterBeanDefinitions(Element root) {  
  2.         <span style="color:#33ff33;">……(注:省略號表示省略掉了代碼)  
  3.         //通過代理delegate解析</span>  
  4.         BeanDefinitionParserDelegate parent = this.delegate;  
  5.         this.delegate = createHelper(readerContext, root, parent);  
  6.   
  7.         preProcessXml(root);  
  8.         parseBeanDefinitions(root, this.delegate);  
  9.         postProcessXml(root);  
  10.   
  11.         this.delegate = parent;  
  12. }  

 

[java] view plaincopy
 
  1. protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {  
  2.         if (delegate.isDefaultNamespace(root)) {  
  3.             <span style="color:#33ff33;">//得到xml文件的子節點,比如各個bean節點</span>  
  4.             NodeList nl = root.getChildNodes();  
  5.             <span style="color:#33ff33;">//對每個節點進行分析處理</span>  
  6.             for (int i = 0; i < nl.getLength(); i++) {  
  7.                 Node node = nl.item(i);  
  8.                 if (node instanceof Element) {  
  9.                     Element ele = (Element) node;  
  10.                     if (delegate.isDefaultNamespace(ele)) {  
  11.                         <span style="color:#33ff33;">//這里是解析過程的調用,對缺省的元素進行分析比如bean元素</span>  
  12.                         parseDefaultElement(ele, delegate);  
  13.                     }  
  14.                     else {  
  15.                         delegate.parseCustomElement(ele);  
  16.                     }  
  17.                 }  
  18.             }  
  19.         }  
  20.         else {  
  21.             delegate.parseCustomElement(root);  
  22.         }  
  23. }  

 

[java] view plaincopy
 
  1. private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {  
  2.         <span style="color:#33ff33;">//對元素Import進行處理</span>  
  3.         if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {  
  4.             importBeanDefinitionResource(ele);  
  5.         }  
  6.         else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {  
  7.             processAliasRegistration(ele);  
  8.         }  
  9.         <span style="color:#33ff33;">//對我們熟悉的bean元素進行處理</span>  
  10.         else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {  
  11.             processBeanDefinition(ele, delegate);  
  12.         }  
  13.         else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {  
  14.             <span style="color:#33ff33;">// recurse</span>  
  15.             doRegisterBeanDefinitions(ele);  
  16.         }  
  17. }  
[java] view plaincopy
 
  1. protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {  
  2.         <span style="color:#33ff33;">//委托給BeanDefinitionParserDelegate來完成對bean元素的處理,這個類包括了具體的bean解析過程。把解析bean文件得到的信息放在BeanDefinition里,它是bean信息的主要載體,也是IOC容器的管理對象。</span>  
  3.         BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);  
  4.         if (bdHolder != null) {  
  5.              bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);  
  6.             try {  
  7.                 <span style="color:#33ff33;">// Register the final decorated instance.  
  8.                                //向IOC容器注冊,實際是放到IOC容器的一個map里</span>         
[java] view plaincopy
 
  1.                                   BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());  
  2.     }  
  3.     catch (BeanDefinitionStoreException ex) {  
  4.         ……  
  5.     }  
  6.     <span style="color:#33ff33;">// Send registration event.  
  7.     //這里向IOC容器發送事件,表示解析和注冊完成</span>  
  8.                     getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));  
  9. }  

         可以看到在processBeanDefinition中對具體bean元素的解析是交給BeanDefinitionParserDelegate來完成的。我們接著看其實現的函數:

[java] view plaincopy
 
  1. public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {  
  2.         <span style="color:#33ff33;">……(省略)</span>  
  3.         AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);  
  4.         if (beanDefinition != null) {  
  5.             <span style="color:#33ff33;">//BeanDefinition解析過程</span>  
  6.                                 ……(省略)  
  7.             String[] aliasesArray = StringUtils.toStringArray(aliases);  
  8.                            <span style="color:#33ff33;">//將解析完的bean定義包裝后返回</span>  
  9.             return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);  
  10.         }  
  11.         return null;  
  12. }  
  13. <p> </p>  


         在這里對定義文件中的bean元素進行解析,得到AbstractBeanDefinition,并用BeanDefinitionHolder封裝后返回。

        下面我們看解析完的bean如何在IOC容器中注冊:在BeanDefinitionReaderUtils中調用的是:

[java] view plaincopy
 
  1. public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)  
  2. throws BeanDefinitionStoreException {  
  3.         <span style="color:#33ff33;">// Register bean definition under primary name.  
  4.         //得到需要注冊bean的名字</span>  
  5.         String beanName = definitionHolder.getBeanName();  
  6.         <span style="color:#33ff33;">//調用IOC來注冊bean的過程,需要得到BeanDefinition</span>  
  7.         registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());  
  8.   
  9.         <span style="color:#33ff33;">// Register aliases for bean name, if any.  
  10.         //將別名通過IOC容器和bean聯系起來進行注冊</span>  
  11.         String[] aliases = definitionHolder.getAliases();  
  12.         if (aliases != null) {  
  13.             for (String aliase : aliases) {  
  14.                 registry.registerAlias(beanName, aliase);  
  15.             }  
  16.         }  
  17. }  


         接著我們看看bean的注冊實現,從上面看到其調用的是BeanDefinitionRegistry的方法registerBeanDefinition完成注冊,跟蹤代碼可知BeanFactory容器的一個實現DefaultListableBeanFactory實現了這個接口并提供了注冊的具體實現:

 

[java] view plaincopy
 
  1. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {  
  2.   
  3.         ......  
  4.         if (beanDefinition instanceof AbstractBeanDefinition) {  
  5.             try {  
  6.                 ((AbstractBeanDefinition) beanDefinition).validate();  
  7.             }  
  8.             catch (BeanDefinitionValidationException ex) {  
  9.                 <span style="color:#33ff33;">//拋出異常BeanDefinitionStoreException</span>  
  10.                 ……  
  11.             }  
  12.         }  
  13.   
  14.         synchronized (this.beanDefinitionMap) {  
  15.             Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);  
  16.             if (oldBeanDefinition != null) {  
  17.                 if (!this.allowBeanDefinitionOverriding) {  
  18.                     <span style="color:#33ff33;">//拋出異常BeanDefinitionStoreException</span>  
  19.                     ……  
  20.                 }  
  21.                 else {  
  22.                     if (this.logger.isInfoEnabled()) {  
  23.                         ……  
  24.                     }  
  25.                 }  
  26.             }  
  27.             else {  
  28.                 this.beanDefinitionNames.add(beanName);  
  29.                 this.frozenBeanDefinitionNames = null;  
  30.             }  
  31.             this.beanDefinitionMap.put(beanName, beanDefinition);  
  32.   
  33.             resetBeanDefinition(beanName);  
  34.         }  
  35. }  

         可以看到整個注冊過程很簡單,就是將bean添加到BeanDefinition的map中。這樣就完成了bean定義在IOC容器中的注冊,就可被IOC容器進行管理和使用了。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
中文字幕亚洲欧美日韩高清| 国产成人中文字幕| 久热精品视频在线| 国产精品久久久久久久av电影| 欧美日韩在线第一页| 日韩免费在线免费观看| 日韩视频免费大全中文字幕| 97国产在线观看| 国产精品扒开腿做爽爽爽的视频| 亚洲精品视频二区| 久久久伊人欧美| 日韩女在线观看| 国产欧美日韩综合精品| 日韩欧美主播在线| 亚洲欧洲在线免费| 国产欧美精品一区二区| 国产精品6699| 欧美精品久久久久| 精品av在线播放| 日韩欧美国产中文字幕| 在线精品播放av| 国产成人综合精品在线| 亚洲无亚洲人成网站77777| 国产精品九九久久久久久久| 中文字幕欧美精品日韩中文字幕| 亚洲欧美日韩另类| 欧美午夜美女看片| 欧美日韩一二三四五区| 中文字幕精品一区久久久久| 91国产美女视频| 国产日产久久高清欧美一区| 97久久伊人激情网| 久久久国产精品免费| 欧美日韩亚洲天堂| 久久久亚洲天堂| 正在播放国产一区| 91久久在线视频| 日韩美女在线观看| 色诱女教师一区二区三区| 尤物99国产成人精品视频| 97在线日本国产| 久久视频这里只有精品| www日韩欧美| 亚洲sss综合天堂久久| 在线观看国产精品91| 在线亚洲国产精品网| 亚洲图中文字幕| 中文字幕av一区二区三区谷原希美| 91精品视频网站| 国产mv免费观看入口亚洲| 日韩小视频网址| 国产91精品久久久久久久| 精品高清一区二区三区| 日本一区二三区好的精华液| 久久久久久国产| 日韩视频免费中文字幕| 一本大道香蕉久在线播放29| 日韩精品在线视频观看| 欧美中文字幕第一页| 欧美一区二区三区图| 欧美在线观看网址综合| 国内免费久久久久久久久久久| 4444欧美成人kkkk| 日韩中文在线视频| 欧美激情第6页| 久久影视免费观看| 九九精品在线观看| 国产精品色视频| 国产精品女主播视频| 国产亚洲欧美一区| 国产精品久久一区| 日韩中文有码在线视频| 亚洲免费视频一区二区| 亚洲国产精品成人av| 疯狂蹂躏欧美一区二区精品| 色综合久久88| 亚洲天堂男人天堂女人天堂| 日韩精品免费一线在线观看| 亚洲性生活视频| 欧美日韩成人黄色| 国产日本欧美一区| 2019中文字幕在线| 伊人久久精品视频| 欧美久久精品午夜青青大伊人| 欧美午夜丰满在线18影院| 亚洲激情视频在线观看| 中文字幕日韩精品在线观看| 欧美电影院免费观看| 日韩欧美在线视频观看| 亚洲成人黄色在线观看| www.日韩免费| 成人午夜在线影院| 成人黄色中文字幕| 国产精品久久久久福利| 国产精品国产亚洲伊人久久| 色黄久久久久久| 日韩av在线直播| 国产成人精品久久| 欧美猛男性生活免费| 国产91色在线免费| 欧美xxxx综合视频| 亚洲老头同性xxxxx| 国产精品视频久久久| 色婷婷成人综合| 亚洲综合国产精品| 久久av中文字幕| 久久免费国产精品1| 清纯唯美日韩制服另类| 久久男人的天堂| 欧美日韩国产一中文字不卡| 国产精品久久久久久久久久久久久久| 久久久久亚洲精品成人网小说| 久久亚洲国产成人| 久久久久久一区二区三区| 亚洲精品视频在线观看视频| 亚洲成人激情小说| 尤物yw午夜国产精品视频| 大伊人狠狠躁夜夜躁av一区| 91chinesevideo永久地址| 国产精品久久久久久久久粉嫩av| 欧美自拍视频在线| 91精品国产乱码久久久久久蜜臀| 性色av一区二区三区在线观看| 亚洲人高潮女人毛茸茸| 欧美做爰性生交视频| 日韩精品视频在线播放| 亚洲国产高清自拍| 性欧美在线看片a免费观看| 精品少妇一区二区30p| 国内精品模特av私拍在线观看| 精品视频久久久| 国产精品久久久久久久久久久不卡| 亚洲精品国产品国语在线| 欧美成人一区二区三区电影| 91免费看片在线| 亚洲欧美制服中文字幕| 欧美激情a∨在线视频播放| 超碰97人人做人人爱少妇| 亚洲人成电影网站色| 日韩在线观看免费高清| 国产成人亚洲综合| 欧美日韩亚洲一区二区三区| 91老司机精品视频| 日韩欧美999| 上原亚衣av一区二区三区| 成人性生交大片免费看视频直播| 欧美亚洲成人精品| 97超碰国产精品女人人人爽| 欧美性猛交xxxx乱大交3| 欧美体内谢she精2性欧美| 亚洲成人精品久久久| 久久久97精品| 久久久91精品| 精品久久久香蕉免费精品视频| 国产91成人在在线播放| 一夜七次郎国产精品亚洲| 国产日韩欧美视频在线| 久久夜色精品亚洲噜噜国产mv| 亚洲成人av中文字幕| 欧美电影免费观看网站| 91影院在线免费观看视频| 欧美激情综合亚洲一二区| 国产91ⅴ在线精品免费观看| 日韩中文字幕视频在线|