Dict.CN 在線詞典, 英語學習, 在線翻譯

          都市淘沙者

          荔枝FM Everyone can be host

          統計

          留言簿(23)

          積分與排名

          優秀學習網站

          友情連接

          閱讀排行榜

          評論排行榜

          Spring 源碼分析:ApplicationContext

          Spring 源碼分析:ApplicationContext

          關鍵詞Spring    ApplicationCont                                          

          分析ApplicationContext
                 Spring的bean包支持通過編碼方式管理和操作bean的基本功能,ApplicationContext
          則以Framework的方式提供BeanFactory的所有功能。使用ApplicationContext,你可以讓
          系統加載你的bean(例如,在Servlet容器初始化ContextLoaderServlet時,通過
          ContextLoader類加載Spring Framework),而不是使用編碼方式來加載。
                 ApplicationContext接口是context包的基礎,位于
          org.springframework.context包里,提供了BeanFactory的所有功能。除此之外, 
          ApplicationContext為了支持Framework的工作方式,提供了以下的功能:
                l.MessageSource,提供了語言信息的國際化支持
                2.提供資源(如URL和文件系統)的訪問支持
                3.為實現了ApplicationListener接口的bean提供了事件傳播支持
                4.為不同的應用環境提供不同的context,例如支持web應用的XmlWebApplicationContext類
          
                下面的源代碼分析主要集中在ApplicationContext接口特有的功能上,如國際化支持,
          資源訪問和bean的事件傳播。
          
          我的問題
                 現在我的問題是,ApplicationContext是如何實現上面提到的功能的?下面的分析
          將作出回答。
          
          準備測試用例
                 1. 首先在類路徑根目錄編寫測試國際化支持的testmsg.xml,并將它加入Spring IDE
          的管理范圍:
                 <beans>
                      <bean id="messageSource" 
                     class="org.springframework.context.support.ResourceBundleMessageSource">
                           <property name="basenames">
                                <list>
                                      <value>message</value>
                                </list>
                           </property>
                      </bean>
                 </beans>
          
                 2. 編寫測試用例,測試國際化支持和資源訪問的功能。
                     public class MsgTest extends TestCase {
                           ApplicationContext ctx = null;
                           public MsgTest(String arg0) {
                                 super(arg0);
                           }
                           protected void setUp() throws Exception {
                                 super.setUp();
                                 ctx = new FileSystemXmlApplicationContext("testmsg.xml");
                           }
                           public void testMessageResource() {
                                 Object[] args = {"我", "你"};
                                 String msg = ctx.getMessage("hello", args, Locale.CHINA);
                                 //System.out.println("msg=" + msg);
                                 assertEquals("我和你", msg);
                                 Resource rs = ctx.getResource("classpath:log4j.properties");
                                 assertTrue(rs.exists());
                          }
                     }
          
                 3. 在類路徑根目錄創建屬性文件message.properties,內容為hello={0}和{1}。
           
                 此時運行TestCase,果然不出所料,Junit視圖的測試狀態是紅條。將打印msg變量的
          語句打開,重新測試,發現"和"字是亂碼。
                 在message.properties文件中將"和"字改為ASCII碼\u548c,重新運行TestCase,
          綠條,測試通過。
                 將testmsg.xml中bean的id改為messageSource1,重新運行測試,出現紅條,
          測試失敗,說明bean的名稱必須是messageSource,這點值得注意。至于其中的原因稍后
          說明。
          
                 ApplicationContext接口通過繼承BeanFactory,MessageSource和ResourceLoader
          三個接口,分別支持管理和操作bean的功能,語言信息的國際化支持以及對資源訪問的支持。
                 AbstractApplicationContect是ApplicationContext的抽象實現類,它的繼承層次較
          為紊亂,我覺得這里應該進行代碼重構。AbstractXmlApplicationContext是
          AbstractApplicationContext的子類,提供了對XML配置文件的支持,它有三個子類,分別
          用于不同的應用環境。
                 對于MessageSource,Spring提供了兩個bean實現,ResourceBundleMessageSource和
          ReloadableResourceBundleMessageSource。前者提供了訪問Properties文件的支持,后者
          添加了無需重啟JVM,重新加載Properties文件的支持。
          ApplicationContext的國際化和資源訪問支持
                 1. 如類層次圖所示,在我們的例子中,FileSystemXmlApplicationContext使用
          DefaultListableBeanFactory裝載和解釋testmsg.xml配置文件(參見代碼分析的
          BeanFactory部分)。
          
                 2. FileSystemXmlApplicationContext根據配置文件的BeanDefinition創建
          ResourceBundleMessageSource,加載<list>元素定義的Properties文件,并保存在
          AbstractApplicationContext的屬性中。當客戶程序調用getMessage方法時,
          AbstractApplicationContext調用ResourceBundleMessageSource的getMessage方法返回
          Message信息。
          
                 3. 至于上節提到的MessageSource的id只能是messageSource,是因為
          AbstractApplicationContext的initMessageSource()方法中,有這樣一段代碼:
                             this.messageSource = (MessageSource) 
                             getBean(MESSAGE_SOURCE_BEAN_NAME);
                     其中MESSAGE_SOURCE_BEAN_NAME的定義為:
                             static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";
                     原因找到了,其實只要稍做代碼重構,即可消除這個缺陷。
                 4. 如類層次圖所示,AbstractApplicationContext繼承了DefaultResourceLoader,
          當客戶程序調用getResource方法時,使用父類中實現的方法來處理。
           
          ApplicationContext的事件傳播
          準備測試用例
                 1. 首先編寫測試用例。
                     public class SenderBeanTest extends TestCase {
                          ApplicationContext ctx = null;
                          protected void setUp() throws Exception {
                              super.setUp();
                              ctx = new FileSystemXmlApplicationContext("testlistener.xml");
                          }
                          public void testSendEmail() {
                              SenderBean sender = (SenderBean)ctx.getBean("sender");
                              String msg = sender.sendMessage("test message");
                              assertEquals("test message", msg);
                          }
                     }
                 2. 接著編寫testlistener.xml配置文件。
                     <beans>
                         <bean id="sender" class="unittest.SenderBean"/>
                         <bean id="listener" class="unittest.MessageListener"/>
                     </beans>
                 3. 最后編寫SenderBean,MessageListener和MessageEvent類。
                     public class SenderBean implements ApplicationContextAware {
                            private ApplicationContext applicationContext;
                            public void setApplicationContext(ApplicationContext applicationContext)
                                      throws BeansException {
                                  this.applicationContext = applicationContext;
                            }
                            public String sendMessage(String msg) {
                                  MessageEvent event = new MessageEvent(msg);
                                  this.applicationContext.publishEvent(event);
                                  return msg;
                            }
                      }
           
                      public class MessageListener implements ApplicationListener {
                            public void onApplicationEvent(ApplicationEvent event) {
                                  if (event instanceof MessageEvent) {
                                        System.out.println("I got the message:" + event.getSource());
                                  }
                            }
                      }
           
                      public class MessageEvent extends ApplicationEvent {
                            public MessageEvent(Object source) {
                                  super(source);
                                  System.out.println(this.getTimestamp() + ":" + source);
                            }
                      }
                     運行測試案例SenderBeanTest,綠條,測試通過。Console窗口出現以下DEBUG
          信息:
                     ……
                     796 DEBUG support.DefaultListableBeanFactory - Returning 
          cached instance of singleton bean 'sender'
                     1085553911796:test message
                     796 DEBUG support.FileSystemXmlApplicationContext - Publishing event 
          in context [org.springframework.context.support.FileSystemXmlApplicationContext;hashCode=13549765]: 
          unittest.MessageEvent[source=test message]
                     I got the message:test message
          
           
          事件傳播的實現
                 1. FileSystemXmlApplicationContext的構造器調用AbstractApplicationContext的
          refresh方法。如圖所示,refresh方法調用refreshListeners方法。
                 2. AbstractApplicationContext的refreshListeners方法使用BeanFactory的
          getBeanOfType方法得到所有ApplicationListener類(本例中是MessageListener),并使用
          addListener方法把它們都放入ApplicationEventMulticasterImpl的Set容器中
          (eventListeners變量)。
                 3. 如圖所示,SenderBean實現ApplicationContextAware接口,并通過
          setApplicationContext方法注入ApplicationContext對象實例。
                 4. 當調用SenderBean類sendMessage方法時,AbstractApplicationContext調用
          publishEvent方法。
                 5. AbstractApplicationContext類的publishEvent方法調用
          ApplicationEventMulticasterImpl類的onApplicationEvent方法。
                 6. ApplicationEventMulticasterImpl通知Set容器中所有的ApplicationListener
          對象,調用它們的onApplicationEvent方法。
           
                 從以上的過程可以看出,ApplicationContext將事件通知所有的
          ApplicationListener。如果ApplicationListener的子類(如MessageListener)只想接受
          指定的事件類型,需要自己編寫過濾代碼,如例子中的if (event instanceof MessageEvent)。

          posted on 2006-03-02 17:09 都市淘沙者 閱讀(1485) 評論(0)  編輯  收藏 所屬分類: Spring+Struts+Hibernate

          主站蜘蛛池模板: 黔江区| 临颍县| 凤凰县| 沂南县| 吉首市| 营口市| 伊金霍洛旗| 乌拉特中旗| 克什克腾旗| 英吉沙县| 甘泉县| 奉贤区| 革吉县| 揭阳市| 凤山市| 丽江市| 房产| 汝南县| 银川市| 衡水市| 滁州市| 志丹县| 资阳市| 台前县| 公安县| 陇川县| 洪湖市| 准格尔旗| 渑池县| 太原市| 牟定县| 肇源县| 遂昌县| 鄯善县| 内黄县| 砚山县| 莱阳市| 汽车| 苏尼特右旗| 本溪| 黄山市|