核心技術-IOC-2

1.2.容器概述

org.springframework.context.ApplicationContext接口負責實例化、配置和組裝bean,即可代表Spring IoC容器。容器通過讀取配置元數據獲得關于實例化、配置和組裝哪些對象的指令。配置元數據用XML、Java注釋或Java代碼表示。它允許您表達組成應用程序的對象以及這些對象之間豐富的相互依賴關系。

Spring提供了幾個ApplicationContext接口的實現。在獨立的應用程序中,可以使用ClassPathXmlApplicationContextFileSystemXmlApplicationContext。雖然XML是定義配置元數據的傳統格式,但是您可以通過提供少量XML配置以聲明方式指示容器支持使用Java注釋或代碼作為元數據格式。

在大多數應用程序場景中,不需要顯式的用戶代碼來創(chuàng)建Spring IoC容器的一個或多個實例。例如,在web應用程序中,一個簡單的8行(大約)樣板web.xml文件通常就足夠了(見Convenient ApplicationContext Instantiation for Web Applications)。如果您使用Spring Tools for Eclipse(一個強大的Eclipse開發(fā)環(huán)境),只需點擊幾下鼠標就可以輕松創(chuàng)建這個樣板配置。

下圖從較高層面展示了Spring是如何工作的。應用程序類與配置元數據相結合,這樣在ApplicationContext創(chuàng)建并初始化之后,您就擁有了一個配置完整且可執(zhí)行的應用程序。

Spring IoC容器

1.2.1.配置元數據

如上圖所示,Spring IoC容器需要某種形式的配置元數據。此配置元數據代表了作為應用程序開發(fā)人員,您訴Spring容器如何實例化、配置和組裝應用程序中的對象。

配置元數據傳統上以一種簡單而直觀的XML格式提供,本章的大部分內容都使用這種格式來描述Spring IoC容器的關鍵概念和特性。

基于XML的元數據并不是唯一允許的配置元數據形式。Spring IoC容器本身與配置元數據的方式是完全解耦的?,F在,許多開發(fā)人員為他們的Spring應用程序選擇基于java的配置。

有關在Spring容器中使用其他形式的元數據的信息,請參見:

  • Annotation-based configuration:Spring2.5引入了對基于注釋的配置元數據的支持。
  • Java-based configuration:從Spring 3.0開始,Spring JavaConfig項目提供的許多特性成為了核心Spring框架的一部分。Starting with Spring 3.0, many features provided by the Spring JavaConfig project became part of the core Spring Framework. 因此,您可以通過使用Java而不是XML文件來定義應用程序類外部的bean。使用這些新特性,請參見@Configuration@Bean、@Import@DependsOn注解。

Spring配置由至少一個(通常是多個)被容器管理的bean定義組成。基于XML的配置元數據通過root元素<beans/>中的<bean/>元素來配置。Java配置通常在@Configuration類中使用@Bean注解的方式來配置。

這些bean定義對應應用程序內的實際對象。比如:服務層對象(service)、數據訪問層對象(DAO)、表示層對象(如Struts的Action,SpringMVC的Controller),還有一些底層基礎設施對象(如Hibernate的SessionFactories、JMS的Queues)等等。通常,不需要在容器中配置細粒度的領域對象(POJO、JavaBean等),因為創(chuàng)建和加載領域對象通常是DAO和service的責任。但是,您可以使用Spring與AspectJ的集成來配置在IoC容器控制之外創(chuàng)建的對象。參見Using AspectJ to dependency-inject domain objects with Spring

下面的例子展示了基于xml的配置元數據的基本結構:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="..." class="...">
        <!-- 這個bean的依賴和配置在這里 -->
    </bean>

    <bean id="..." class="...">
        <!-- 這個bean的依賴和配置在這里 -->
    </bean>

    <!-- 更多的bean定義 -->

</beans>
  • id屬性是標識單個bean定義的字符串。
  • class屬性定義bean的類型并使用完全限定的類名。

id屬性的值指向對象。本例中沒有關于依賴項的配置示例。更多信息請參見Dependencies。

1.2.2.實例化一個容器

在下面示例代碼中,提供給ApplicationContext構造函數的路徑或路徑列表是資源路徑字符串,這些資源路徑字符串允許容器從各種外部資源(如本地文件系統、Java CLASSPATH等)加載配置元數據。

ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

在了解了Spring的IoC容器之后,您可能想了解更多關于Spring的Resource抽象(如參考資料所述),它為從URI語法中定義的路徑讀取InputStream提供了一種方便的機制。特別是,Resource用于構建應用程序上下文,如Application Contexts and Resource Paths所述。

以下示例顯示了服務層對象(services.xml)配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- services -->

    <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl">
        <property name="accountDao" ref="accountDao"/>
        <property name="itemDao" ref="itemDao"/>
        <!-- 這個bean的其他依賴和配置在這里 -->
    </bean>

    <!-- 更多的服務層bean定義在這里 -->

</beans>

下面的示例顯示了數據訪問對象(dao.xml)配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="accountDao"
        class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
        <!-- 這個bean的其他依賴和配置在這里 -->
    </bean>

    <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
        <!-- 這個bean的其他依賴和配置在這里 -->
    </bean>

    <!-- 更多數據訪問對象的bean定義在這里 -->

</beans>

在上面的例子中,服務層由PetStoreServiceImpl類和JpaAccountDaoJpaItemDao類型的兩個數據訪問對象組成(基于JPA ORM)。namme元素指的是JavaBean屬性的名稱,而ref元素指的是另一個bean定義的名稱。 idref元素之間的這種鏈接表示了對象之間的依賴關系。有關配置對象依賴關系的詳細信息,請參見Dependencies

組合基于XML的配置

將bean定義拆分成多個XML文件是很有用的。通常,每個單獨的XML配置文件代表體系結構中的一個邏輯層或模塊。

可以使用ApplicationContext構造函數從所有這些XML文件加載bean定義。這個構造函數接受多個Resource路徑,如前一節(jié)所示。或者,使用<import/>元素從另一個或多個文件加載bean定義。下面的例子展示了如何做到這一點:

<beans>
    <import resource="services.xml"/>
    <import resource="resources/messageSource.xml"/>
    <import resource="/resources/themeSource.xml"/>

    <bean id="bean1" class="..."/>
    <bean id="bean2" class="..."/>
</beans>

在上面的示例中,外部bean定義從三個文件加載:services.xmlmessageSource.xmlthemeSource.xml。所有導入文件路徑都相對于執(zhí)行導入的定義文件,因此services.xml必須與執(zhí)行導入的文件位于相同的目錄或類路徑位置,而messageSource.xmlthemeSource.xml必須位于導入文件位置下面的resources目錄里。如您所見,前面的斜杠被忽略了。但是,考慮到這些路徑是相對的,最好不要使用斜杠。導入的文件的內容(包括頂級<beans/>元素)必須是有效的基于Spring Schema的XML bean定義。

可以使用.. /來引用父目錄中的文件,但不建議這樣做。這樣做將創(chuàng)建對當前應用程序之外的文件的依賴關系。特別是,不建議對classpath:類型的URL(例如,classpath:../services.xml)使用../,因為運行解析過程會選擇最近的類路徑根,然后查看其父目錄。類路徑的更改可能導致選擇不同的、不正確的目錄。

您可以始終使用完全限定的資源路徑,而不是相對路徑:例如,file:C:/config/services.xmlclasspath:/config/services.xml。但是,請注意,您這樣會將應用程序的配置耦合到特定的絕對位置。通常,最好為這些絕對位置保留一個間接位置——例如,通過在運行時根據JVM系統屬性解析的${…}占位符。

命名空間本身提供了導入指令功能。除了普通bean定義之外,Spring提供的XML名稱空間中還提供了更多的配置特性——例如,contextutil名稱空間。

1.2.3.使用容器

ApplicationContext是一個高級工廠的接口,該工廠維護了不同bean及其依賴項的注冊表。通過使用T getBean(String name, Class<T> requiredType)方法,您可以獲取bean的實例。

ApplicationContext允許你讀取并訪問bean定義,如下面的例子所示:

// create and configure beans
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");

// retrieve configured instance
PetStoreService service = context.getBean("petStore", PetStoreService.class);

// use configured instance
List<String> userList = service.getUsernameList();

最靈活的變體是GenericApplicationContext,它可以與reader結合使用——例如,XML文件使用XmlBeanDefinitionReader,如下例所示:

GenericApplicationContext context = new GenericApplicationContext();
new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml");
context.refresh();

您可以在相同的ApplicationContext上混合使用不同的reader,以從不同的配置源讀取bean定義。

然后可以使用getBean來獲取bean的實例。ApplicationContext接口有一些其他的方法用于獲取bean,但是,理想情況下,應用程序代碼不應該使用它們。實際上,您的應用程序代碼根本不應該調用getBean()方法,因此也根本不需要依賴于Spring的API。例如,Spring與web框架的集成為各種web框架組件(如controller和JSF bean)提供了依賴注入,允許您通過元數據(如自動裝配注解)聲明對特定bean的依賴。

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 接下來介紹在Spring Framework中不可或缺的那些技術。 其中最重要的非控制反轉(IoC)容器莫屬。在介...
    JiinYuu閱讀 288評論 0 0
  • spring官方參考文檔的這一部分涵蓋了Spring框架絕對不可或缺的所有技術。散人閑來無事,做個知識的搬運工。此...
    WalkByte閱讀 368評論 0 1
  • 1.2. 容器概述 org.springframework.context.ApplicationContext接...
    遠去的青閱讀 139評論 0 0
  • (上一篇內容篇幅過多,閱讀理解起來比較費力,今后細分小節(jié),形成小篇幅閱讀) 1.3 Bean Overview (...
    WalkByte閱讀 286評論 0 1
  • 我是黑夜里大雨紛飛的人啊 1 “又到一年六月,有人笑有人哭,有人歡樂有人憂愁,有人驚喜有人失落,有的覺得收獲滿滿有...
    陌忘宇閱讀 8,822評論 28 54

友情鏈接更多精彩內容