OMG,到底在尋找什么..................
          (構(gòu)造一個完美的J2EE系統(tǒng)所需要的完整知識體系)
          posts - 198,  comments - 37,  trackbacks - 0

          原貼地址:http://book.csdn.net/bookfiles/111/1001113461.shtml

          一.Spring IOC反轉(zhuǎn)控制 BeanFactory

          Spring IoC
          設(shè)計的核心是 org.springframework.beans 包,它的設(shè)計目標是與 JavaBean 組件一起使用。這個包通常不是由用戶直接使用,而是由服務(wù)器將其用作其他多數(shù)功能的底層中介。下一個最高級抽象是 BeanFactory 接口,它是工廠設(shè)計模式的實現(xiàn),允許通過名稱創(chuàng)建和檢索對象。 BeanFactory 也可以管理對象之間的關(guān)系。

          BeanFactory 支持兩個對象模型。

          單態(tài)模型:它提供了具有特定名稱的對象的共享實例,可以在查詢時對其進行檢索。 Singleton 是默認的也是最常用的對象模型,對于無狀態(tài)服務(wù)對象很理想。

          原型模型:它確保每次檢索都會創(chuàng)建單獨的對象。在每個用戶都需要自己的對象時,原型模型最適合。

          bean 工廠的概念是 Spring 作為 IoC 容器的基礎(chǔ), IoC 將處理事情的責(zé)任從應(yīng)用程序代碼轉(zhuǎn)移到框架。 Spring 框架使用 JavaBean 屬性和配置數(shù)據(jù)來指出必須設(shè)置的依賴關(guān)系。

          1 BeanFactory

          BeanFactory 實際上是實例化,配置和管理眾多 bean 的容器。這些 bean 通常會彼此合作,因而它們之間會產(chǎn)生依賴。 BeanFactory 使用的配置數(shù)據(jù)可以反映這些依賴關(guān)系(一些依賴可能不像配置數(shù)據(jù)一樣可見,而是在運行期作為 bean 之間程序交互的函數(shù))。

          一個 BeanFactory 可以用接口 org.springframework.beans.factory.BeanFactory 表示,這個接口有多個實現(xiàn)。最常使用的簡單的 BeanFactory 實現(xiàn)是 org.springframework.beans.factory. xml.XmlBeanFactory (這里提醒一下, ApplicationContext BeanFactory 的子類,所以大多數(shù)的用戶更喜歡使用 ApplicationContext XML 形式)。

          雖然大多數(shù)情況下,幾乎所有被 BeanFactory 管理的用戶代碼都不需要知道 BeanFactory ,但是 BeanFactory 還是以某種方式實例化。可以使用下面的代碼實例化 BeanFactory

          InputStream is = new FileInputStream("beans.xml");
          XmlBeanFactory factory = new XmlBeanFactory(is);

          也可以使用下列代碼實例化 BeanFactory

          ClassPathResource res = new ClassPathResource("beans.xml");
          XmlBeanFactory factory = new XmlBeanFactory(res);

          實例化 BeanFactory 還可以采用如下代碼。

          ClassPathXmlApplicationContext appContext = new ClassPathXmlApplication Context(?
          ???new String[] {"applicationContext.xml", "applicationContext-part2. xml"});

          // of course, an ApplicationContext is just a BeanFactory
          BeanFactory factory = (BeanFactory) appContext;

          很多情況下,用戶代碼不需要實例化 BeanFactory ,因為 Spring 框架代碼會做這件事。例如, Web 層提供支持代碼,在 J2EE Web 應(yīng)用啟動過程中自動載入一個 Spring ApplicationContext 。這個聲明過程在這里描述。

          編程操作 BeanFactory 將會在后面提到,下面部分將集中描述 BeanFactory 的配置。

          一個最基本的 BeanFactory 配置由一個或多個它所管理的 Bean 定義組成。在一個 XmlBeanFactory 中,根節(jié)點 beans 中包含一個或多個 bean 元素。

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework. org/dtd/spring-beans.dtd"> <beans>?
          ?????? <bean id="..." class="...">
          ???????...
          ?
          ?????</bean>?
          ???????<bean id="..." class="...">
          ????????...
          ???????
          </bean>
          </beans>
          ...

          2 BeanDefinition

          一個 XmlBeanFactory 中的 Bean 定義包括的內(nèi)容如下。

          classname :這通常是 bean 真正的實現(xiàn)類。但是,如果一個 bean 使用一個靜態(tài)工廠方法所創(chuàng)建,而不是被普通的構(gòu)造函數(shù)創(chuàng)建,那么這實際上就是工廠類的 classname

          bean 行為配置元素:它聲明這個 bean 在容器的行為方式(比如 prototype singleton 、自動裝配模式、依賴檢查模式、初始化和析構(gòu)方法)。

          構(gòu)造函數(shù)的參數(shù)和新創(chuàng)建 bean 需要的屬性:舉一個例子,一個管理連接池的 bean 使用的連接數(shù)目(即可以指定為一個屬性,也可以作為一個構(gòu)造函數(shù)參數(shù))或者池的大小限制。

          和這個 bean 工作相關(guān)的其他 bean :比如它的合作者(同樣可以作為屬性或者構(gòu)造函數(shù)的參數(shù)),這個也被叫做依賴。

          上面列出的概念直接轉(zhuǎn)化為組成 bean 定義的一組元素。這些元素在表 6-1 中列出,它們每一個都有更詳細的說明的鏈接。

          6-1? Bean 定義的解釋

          ???

          ???

          class

          bean 的類

          id name

          bean 的標志符 (id name)

          singleton prototype

          Singleton 的使用與否

          構(gòu)造函數(shù)參數(shù)

          設(shè)置 bean 的屬性和合作者

          bean 的屬性

          設(shè)置 bean 的屬性和合作者

          自動裝配模式

          自動裝配協(xié)作對象

          依賴檢查模式

          依賴檢查

          初始化模式

          生命周期接口

          析構(gòu)方法

          生命周期接口

          意, bean 定義可以表示為真正的接口 org.springframework.beans.factory.config.BeanDefinition 以及它的各種子接口和實現(xiàn)。然而,絕大多數(shù)的用戶代碼不需要與 BeanDefination 直接接觸。

          3 bean

          class 屬性通常是強制性的,有兩種用法。在絕大多數(shù)情況下, BeanFactory 直接調(diào)用 bean 的構(gòu)造函數(shù)來“ new ”一個 bean (相當于調(diào)用 new Java 代碼), class 屬性指定了需要創(chuàng)建的 bean 的類。在比較少的情況下, BeanFactory 調(diào)用某個類的靜態(tài)的工廠方法來創(chuàng)建 bean class 屬性指定了實際包含靜態(tài)工廠方法的那個類(至于靜態(tài)工廠方法返回的 bean 的類型是同一個類還是完全不同的另一個類,這并不重要)。

          1 )通過構(gòu)造函數(shù)創(chuàng)建 bean

          當使用構(gòu)造函數(shù)創(chuàng)建 bean 時,所有普通的類都可以被 Spring 使用,并且和 Spring 兼容。這就是說,被創(chuàng)建的類不需要實現(xiàn)任何特定的接口或者按照特定的樣式進行編寫。僅僅指定 bean 的類就足夠了。然而,根據(jù) bean 使用的 IoC 類型,你可能需要一個默認的(空的)構(gòu)造函數(shù)。

          另外, BeanFactory 并不局限于管理真正的 JavaBean ,它也能管理任何你想讓它管理的類。雖然很多使用 Spring 的人喜歡在 BeanFactory 中用真正的 JavaBean (僅包含一個默認的(無參數(shù)的)構(gòu)造函數(shù),在屬性后面定義相對應(yīng)的 setter getter 方法),但是在你的 BeanFactory 中也可以使用特殊的非 bean 樣式的類。舉例來說,如果你需要使用一個遺留下來的完全沒有遵守 JavaBean 規(guī)范的連接池,不要擔(dān)心, Spring 同樣能夠管理它。

          使用 XmlBeanFactory 你可以像下面這樣定義你的 bean class

          <bean id="exampleBean" class="examples.ExampleBean"/>
          <bean name="anotherExample" class="examples.ExampleBeanTwo"/>

          至于為構(gòu)造函數(shù)提供(可選的)參數(shù),以及對象實例創(chuàng)建后設(shè)置實例屬性,將會在后面敘述。

          2 )通過靜態(tài)工廠方法創(chuàng)建 bean

          當你定義一個使用靜態(tài)工廠方法創(chuàng)建的 bean ,同時使用 class 屬性指定包含靜態(tài)工廠方法的類,這個時候需要 factory-method 屬性來指定工廠方法名。 Spring 調(diào)用這個方法(包含一組可選的參數(shù))并返回一個有效的對象,之后這個對象就完全和構(gòu)造方法創(chuàng)建的對象一樣。用戶可以使用這樣的 bean 定義在遺留代碼中調(diào)用靜態(tài)工廠。

          下面是一個 bean 定義的例子,聲明這個 bean 要通過 factory-method 指定的方法創(chuàng)建。注意,這個 bean 定義并沒有指定返回對象的類型,只指定包含工廠方法的類。在這個例子中, createInstance 必須是 static 方法。

          <bean id="exampleBean" ?class="examples.ExampleBean2" ?factory-method="createInstance"/>

          至于為工廠方法提供(可選的)參數(shù),以及對象實例被工廠方法創(chuàng)建后設(shè)置實例屬性,將會在后面敘述。

          3 )通過實例工廠方法創(chuàng)建 bean

          使用一個實例工廠方法(非靜態(tài)的)創(chuàng)建 bean 和使用靜態(tài)工廠方法非常類似,調(diào)用一個已存在的 bean (這個 bean 應(yīng)該是工廠類型)的工廠方法來創(chuàng)建新的 bean

          使用這種機制, class 屬性必須為空,而且 factory-bean 屬性必須指定一個 bean 的名字,這個 bean 一定要在當前的 bean 工廠或者父 bean 工廠中,并包含工廠方法。而工廠方法本身仍然要通過 factory-method 屬性設(shè)置。

          下面是一個例子。

          <!-- The factory bean, which contains a method called??createInstance -->
          <bean id="myFactoryBean"class="...">?
          ? ...
          </bean>

          <!-- The bean to be created via the factory bean -->
          <bean id="exampleBean" ?factory-bean="myFactoryBean" ?factory-method="createInstance"/>

          雖然我們要在后面討論設(shè)置 bean 的屬性,但是,這個方法意味著工廠 bean 本身能夠被容器通過依賴注射來管理和配置。

          4 Bean 的標志符( id name

          每一個 bean 都有一個或多個 id (也叫做標志符或名字,這些名詞說的是一回事)。這些 id 在管理 bean BeanFactory ApplicationContext 中必須是惟一的。一個 bean 差不多總是只有一個 id ,但是,如果一個 bean 有超過一個的 id ,那么另外的那些本質(zhì)上可以認為是別名。

          在一個 XmlBeanFactory 中(包括 ApplicationContext 的形式),你可以用 id 或者 name 屬性來指定 bean id(s) ,并且在這兩個或其中一個屬性中至少指定一個 id id 屬性允許你指定一個 id ,并且它在 XML DTD (定義文檔)中作為一個真正的 XML 元素的 ID 屬性被標記,所以 XML 解析器能夠在其他元素指回向它的時候做一些額外的校驗。正因如此,用 id 屬性指定 bean id 是一個比較好的方式。然而, XML 規(guī)范嚴格限定了在 XML ID 中合法的字符。通常這并不是真正限制你,但是,如果你有必要使用這些字符(在 ID 中的非法字符),或者你想給 bean 增加其他的別名,那么你可以通過 name 屬性指定一個或多個 id (用逗號或分號分隔)。

          5 Singleton 的使用與否

          Beans 被定義為兩種部署模式中的一種: singleton non-singleton (后一種也叫做 prototype ,盡管這個名詞用的不精確)。如果一個 bean singleton 形態(tài)的,那么就只有一個共享的實例存在,所有和這個 bean 定義的 id 符合的 bean 請求都會返回這個惟一的、特定的實例。

          如果 bean non-singleton prototype 模式部署的話,對這個 bean 的每次請求都會創(chuàng)建一個新的 bean 實例。這對于每個 user 需要一個獨立的 user 對象的情況是非常理想的。

          Beans 默認被部署為 singleton 模式,除非你指定。要記住把部署模式變?yōu)?/span> non-singletion prototype )后,每一次對這個 bean 的請求都會導(dǎo)致一個新創(chuàng)建的 bean ,而這可能并不是你真正想要的。所以,僅僅在絕對需要的時候才把模式改成 prototype

          在下面這個例子中,兩個 bean 一個被定義為 singleton ,而另一個被定義為 non-singleton prototype )。客戶端每次向 BeanFactory 請求都會創(chuàng)建新的 exampleBean ,而 AnotherExample 僅僅被創(chuàng)建一次,在每次對它請求都會返回這個實例的引用。

          <bean id="exampleBean" ?class="examples.ExampleBean" singleton="false"/>
          <bean name="yetAnotherExample" ?class="examples.ExampleBeanTwo" singleton="true"/>

          注意,當部署一個 bean prototype 模式,這個 bean 的生命周期就會有稍許改變。 通過定義, Spring 無法管理一個 non-singleton/prototype bean 的整個生命周期,因為當它創(chuàng)建之后,它被交給客戶端,而且容器根本不再跟蹤它了。當說起 non-singleton/prototype bean 的時候,你可以把 Spring 的角色想像成“ new ”操作符的替代品。從那之后的任何生命周期方面的事情都由客戶端來處理。




          二.Spring IOC反轉(zhuǎn)控制 ApplicationContext

          beans 包提供了以編程的方式管理和操控 bean 的基本功能,而 context 包增加了 ApplicationContext ,它以一種更加面向框架的方式增強了 BeanFactory 的功能。多數(shù)用戶可以以一種完全的聲明式方式來使用 ApplicationContext ,甚至不用去手工創(chuàng)建它,但是卻去依賴像 ContextLoader 的支持類,在 J2EE Web 應(yīng)用的啟動進程中用它啟動 ApplicationContext 。當然,這種情況下還可以以編程的方式創(chuàng)建一個 ApplicationContext

          Context 包的基礎(chǔ)是位于 org.springframework.context 包中的 ApplicationContext 接口。它是由 BeanFactory 接口集成而來,提供 BeanFactory 所有的功能。為了以一種更像面向框架的方式工作, context 包使用分層和有繼承關(guān)系的上下文類,包括:

          1 MessageSource ,提供對 i18n 消息的訪問;
          2 .資源訪問,比如 URL 和文件;
          3 .事件傳遞給實現(xiàn)了 ApplicationListener 接口的 bean
          4 .載入多個(有繼承關(guān)系)上下文類,使得每一個上下文類都專注于一個特定的層次,比如應(yīng)用的 Web 層。

          因為 ApplicationContext 包括了 BeanFactory 所有的功能,所以通常建議先于 BeanFactory 使用,除了有限的一些場合,比如在一個 Applet 中,內(nèi)存的消耗是關(guān)鍵的,每千字節(jié)都很重要。接下來,敘述 ApplicationContext BeanFactory 的基本能力上增加的功能。

          1 )使用 MessageSource

          ApplicationContext 接口繼承 MessageSource 接口,所以提供了 messaging 功能( i18n 或者國際化)。同 NestingMessageSource 一起使用,就能夠處理分級的信息,這些是 Spring 提供的處理信息的基本接口。讓我們很快瀏覽一下這里定義的方法。

          String getMessage (String code Object[] args String default Locale loc) :這個方法是從 MessageSource 取得信息的基本方法。如果對于指定的 locale 沒有找到信息,則使用默認的信息。傳入的參數(shù) args 被用來代替信息中的占位符,這個是通過 Java 標準類庫的 MessageFormat 實現(xiàn)的。

          String getMessage (String code Object[] args Locale loc) :本質(zhì)上和上一個方法是一樣的,除了一點區(qū)別:沒有默認值可以指定;如果信息找不到,就會拋出一個 NoSuchMessage Exception

          String getMessage(MessageSourceResolvable resolvable Locale locale) :上面兩個方法使用的所有屬性都可以封裝到一個叫做 MessageSourceResolvable 的類中,你可以通過這個方法直接使用它。

          ApplicationContext 被加載的時候,它會自動查找在 context 中定義的 MessageSource bean ,這個 bean 必須叫做 message source 。如果找到了這樣的一個 bean ,所有對上述方法的調(diào)用將會被委托給找到的 message source 。如果沒有找到 message source ApplicationContext 將會嘗試查它的父親是否包含這個名字的 bean 。如果有,它將會把找到的 bean 作為 Message Source 。如果它最終沒有找到任何信息源,一個空的 StaticMessageSource 將會被實例化,使它能夠接受上述方法的調(diào)用。

          Spring 目前提供了兩個 MessageSource 的實現(xiàn),它們是 ResourceBundleMessageSource StaticMessageSource 。它們都實現(xiàn)了 NestingMessageSource 以便能夠嵌套地解析信息。 StaticMessageSource 很少被使用,但是它提供以編程的方式向 source 增加信息。 Resource BundleMessageSource 用得更多一些,我們將提供它的一個例子。

          <beans>?
          ? <bean id="messageSource"
          ?????????????? class="org.springframework.context.support.ResourceBundle MessageSource">

          ??????? <property name="basenames">
          ??????????? <list>
          ?????????????? <value>format</value>
          ??????????????? <value>exceptions</value>
          ??????????????? <value>windows</value>
          ??????????? </list>
          ??????? </property>
          ??? </bean>

          </beans>

          這段配置假定你在 classpath 3 resource bundle ,分別叫做 f format exceptions windows 使用 JDK 通過 ResourceBundle 解析信息的標準方式,任何解析信息的請求都會被處理。

          2 )事件傳遞

          ApplicationContext 中的事件處理是通過 ApplicationEvent 類和 ApplicationListener 接口來提供的。如果上下文中部署了一個實現(xiàn)了 ApplicationListener 接口的 bean ,每次一個 ApplicationEvent 發(fā)布到 ApplicationContext 時,那個 bean 就會被通知。實質(zhì)上,這是標準的 Observer 設(shè)計模式。 Spring 提供了 3 個標準事件,如表 6-2 所示。

          6-2? 內(nèi)置事件

          ???

          ???

          ContextRefreshedEvent

          ApplicationContext 已經(jīng)初始化或刷新后發(fā)送的事件。這里初始化意味著所有的 bean 被裝載, singleton 被預(yù)實例化,以及 ApplicationContext 已準備好

          ContextClosedEvent

          當使用 ApplicationContext close() 方法結(jié)束上下文的時候發(fā)送的事件。這里結(jié)束意味著: singleton 被銷毀 ?

          RequestHandledEvent

          一個與 Web 相關(guān)的事件,告訴所有的 bean 一個 HTTP 請求已經(jīng)被響應(yīng)了(這個事件將會在一個請求結(jié)束后被發(fā)送)。注意,這個事件只能應(yīng)用于使用了 Spring DispatcherServlet Web 應(yīng)用

          同樣也可以實現(xiàn)自定義的事件。通過調(diào)用 ApplicationContext publishEvent() 方法,并且指定一個參數(shù),這個參數(shù)是你自定義的事件類的一個實例。我們來看一個例子,首先是 ApplicationContext

          <bean id="emailer" class="example.EmailBean">?
          ??? <property name="blackList">
          ??????? <list>
          ????????????? <value>black@list.org</value>
          ????????????? <value>white@list.org</value>
          ????????????? <value>john@doe.org</value>
          ??????? </list>
          ??? </property>

          </bean>

          <bean id="blackListListener" class="example.BlackListNotifier">?
          ????<property name="notificationAddress">
          ??????? <value>spam@list.org</value>
          ??? </property>

          </bean>

          然后是實際的bean。

          public class EmailBean implements ApplicationContextAware {

          ??? /** the blacklist */
          ??? private List blackList;
          ??
          ??? public void setBlackList(List blackList) {
          ??????? this.blackList = blackList;
          ??? }
          ?
          ??? public void setApplicationContext(ApplicationContext ctx) {
          ??????? this.ctx = ctx;
          ??? }
          ?
          ??? public void sendEmail(String address, String text) {

          ??????? if (blackList.contains(address)) {
          ??????????? BlackListEvent evt = new BlackListEvent(address, text);
          ??????????? ctx.publishEvent(evt);
          ??????????? return;
          ??????? }
          ?
          ??????? // send email
          ??? }

          }

          public class BlackListNotifier implement ApplicationListener {

          ??? /** notification address */
          ??? private String notificationAddress;

          ???public void setNotificationAddress(String notificationAddress) {
          ??????? this.notificationAddress = notificationAddress;
          ??? }

          ??? public void onApplicationEvent(ApplicationEvent evt) {
          ??????? if (evt instanceof BlackListEvent) {
          ??????????? // notify appropriate person
          ??????? }
          ??? }

          }

          ?

          3 )在 Spring 中使用資源

          很多應(yīng)用程序都需要訪問資源。 Spring 提供了一個清晰透明的方案,以一種協(xié)議無關(guān)的方式訪問資源。 ApplicationContext 接口包含一個方法( getResource(String) )負責(zé)這項工作。

          Resource 類定義了幾個方法,這幾個方法被所有的 Resource 實現(xiàn)所共享,資源功能如表 6-3 所示。

          6-3? 資源功能

          ???

          ???

          getInputStream()

          InputStream 打開資源,并返回這個 InputStream

          exists()

          檢查資源是否存在,如果不存在,返回 false

          isOpen()

          如果這個資源不能打開多個流,將會返回 true 。因為除了基于文件的資源,一些資源不能被同時多次讀取,它們就會返回 false

          getDescription()

          返回資源的描述,通常是全限定文件名或者實際的 URL

          Spring 提供了幾個 Resource 的實現(xiàn)。它們都需要一個 String 表示的資源的實際位置。依據(jù)這個 String Spring 將會自動為你選擇正確的 Resource 實現(xiàn)。當向 ApplicationContext 請求一個資源時, Spring 首先檢查你指定的資源位置,尋找任何前綴。根據(jù)不同的 Application Context 的實現(xiàn),不同的 Resource 實現(xiàn)可被使用。 Resource 最好是使用 ResourceEditor 來配置,比如 XmlBeanFactory




          posted on 2006-11-01 10:39 OMG 閱讀(727) 評論(0)  編輯  收藏 所屬分類: Spring

          <2006年11月>
          2930311234
          567891011
          12131415161718
          19202122232425
          262728293012
          3456789

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          IT風(fēng)云人物

          文檔

          朋友

          相冊

          經(jīng)典網(wǎng)站

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 庆云县| 洪泽县| 罗甸县| 台东市| 陇西县| 石家庄市| 扶绥县| 佛坪县| 中卫市| 枣阳市| 邯郸县| 北辰区| 武冈市| 菏泽市| 聂拉木县| 平原县| 蒙自县| 正镶白旗| 吕梁市| 海原县| 微山县| 台江县| 读书| 沂南县| 扶绥县| 大埔区| 厦门市| 应城市| 巴塘县| 乃东县| 碌曲县| 改则县| 灵武市| 开远市| 麟游县| 郸城县| 于都县| 铁岭县| 大化| 监利县| 绥化市|