IoC容器2——容器總覽

org.springframework.context.ApplicationContext 表明 Spring IoC 容器,並負責實例化,配置和組裝上述 bean 。容器經過讀取配置元數據得到哪些對象須要實例化、配置和組裝的指定。配置元數據能夠在XML、Java註解和Java代碼中配置。它運行你描述組成你應用程序的對象和對象之間複雜的關係。web

Spring提供了一些開箱即用的ApplicationContext接口的實現。在獨立的應用程序中,通常能夠建立ClassPathXmlApplicationContext或FileSystemXmlApplicationContext的實例。雖然XML一直是傳統的定義配置元數據的格式,但也能夠指示容器使用Java註解或者代碼做爲元數據的格式,並提供少許的XML配置以聲明的方式啓用這些額外的元數據格式的支持。spring

在大多數的應用場景,用戶代碼並不須要明確的實例化一個或多個Spring IoC容器的實例。例如,在web應用場景中,程序的web.xml文件中定義一個8行左右的web部署描述符XML就能夠知足要求。若是使用的是基於Eclipse的 Spring Tool Suite開發環境,該配置能夠很容易地用敲幾下鼠標或鍵盤建立。sql

下圖是展現 Spring 如何工做的高級視圖。應用程序的類與配置元數據進行結合,以便在 ApplicationContext建立和初始化後,擁有一個徹底配置和可執行的系統或應用程序。session

輸入圖片說明

1 配置元數據

如上述圖所示,Spring IoC 容器使用配置元數據;這個配置元數據表明了應用程序開發人員告訴 Spring 容器在應用程序中如何來實例化,配置和組裝對象。架構

傳統的配置元數據是一個簡單而直觀的 XML 格式。框架

基於 XML 的元數據並非配置元數據的惟一容許的形式。 Spring IoC容器自己是徹底與配置元數據的實際寫入格式分離的。如今,許多開發人員選擇基於 Java 的配置來開發他們的應用程序。函數

其餘格式的元數據:ui

  • 基於註解的配置:Spring 2.5 的推出了基於註解的配置元數據支持;
  • 基於Java的配置:Spring3.0 開始,由 Spring JavaConfig 項目提供的不少功能成爲核心 Spring 框架的一部分。所以,能夠經過使用Java,而不是 XML 文件中定義外部 bean 到你的應用程序類。要使用這些新功能,參閱 @Configuration,@Bean@Import 和 @DependsOn 註解。

Spring 配置至少一個、一般不止一個 bean 由容器來管理。基於 XML 的配置元數據將這些 bean 配置爲<bean/>元素,並放置到<beans/> 元素內部。 Java 配置一般在 @Configuration註解的類中使用 @Bean 註解的方法。this

這些bean定義對應組成應用程序的實際對象。一般會定義服務層對象,數據訪問對象(DAO),展現對象,例如Structs Action實例,基礎設施的對象,如 Hibernate 的 SessionFactories,JMS Queues等等。一般,在容器中不配置細粒度的域對象,由於一般由DAO和業務邏輯負責建立和加載域對象(這裏的域對象應該相似於POJO)。可是你可使用 Spring 和 AspectJ的集成配置在 IoC 容器的控制以外建立的對象。url

如下示例顯示基於 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
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>

id 屬性是一個字符串,惟一識別一個獨立的 bean 定義。class 屬性定義了 bean 的類型,使用完整的類名。 id 屬性的值指向協做對象。在XML 配置協做對象未在本例中示給出(關於協做對象這句,應該是指在依賴關係的引用時使用id屬性,這個例子並無給出依賴關係的引用)。

2 實例化容器

實例化 Spring IoC 容器是簡單的。提供給ApplicationContext構造函數的位置路徑其實是容器從各類外部資源(如本地文件系統、Java ClassPath等)加載配置元數據的資源字符串。

ApplicationContext context =
    new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});

當了解了Spring IoC容器後,由必要了解Spring Resource抽象概念,它提供了一種便捷的機制從uri語法定義的位置讀取InputStream。一般,Resource路徑用於構造應用上下文。

下面的例子展現了業務層對象(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
        http://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"/>
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for services go here -->

</beans>

下面的例子展現數據接入層(daos.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
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="accountDao"
        class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions for data access objects go here -->

</beans>

上面的例子中,業務層包含了PetStoreServiceImpl類和兩個類型爲JpaAccountDao和JpaItemDao數據接入對象(基於JPA對象/關係映射標準)。property元素的 name 屬性是指 JavaBean 屬性的名稱,而 ref 屬性引用另外一個 bean 定義的名稱。 id 和 ref 元素之間的這種聯繫表達了協做對象之間的依賴關係。

撰寫基於XML的配置元數據

bean的定義跨越多個XML文件是有用的。通常一個XML配置文件表明程序架構中的一個業務層或業務模塊。

可使用應用上下文的構造函數從全部XML段中加載bean定義。構造函數加載多個Resource地址,正如上文的例子那樣。另外一種方法,可使用一個或多個<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.xml,messageSource.xml和themeSource.xml。全部的位置路徑都相對於導入文件的路徑,所以services.xml必須位於導入它的文件的相同文件夾或類路徑,而messageSource.xml和themeSource.xml需位於導入它們的文件路徑的resources下。前面的斜線能夠被忽略,但考慮到這些路徑是相對的,最好不使用斜線。被導入的文件(要包含頂級元素<beans/>),必須是有效的bean定義(根據Spring Schema)。

使用相對路徑../是可行的,可是並不推薦。這樣作會對當前應用程序以外的文件產生依賴。通常狀況下,這種相對路徑並不推薦用於classpach:URLs的格式(例如,classpath: ../services.xml),運行時解析進程選擇最近的classpath根目錄而後查找它的父文件夾。classpath配置改變也許會致使選擇了一個不一樣的、錯誤的文件夾。

應該老是使用絕對路徑代替相對路徑:例如"file:C:/config/services.xml"或者"classpath:/config/services.xml"。然而,應當注意這樣應用程序就和特定的絕對路徑耦合了。因此一般使用間接的方式應對這種絕對路徑,例如使用在JVM系統運行時解析的佔位符${...}。

XML文件中的import指令是由beans的命名空間自己提供的功能。不在beans命名空間中的更多配置功能由Spring的可選命名空間提供,例如context和util命名空間。

Groovy Bean Definition DSL

做爲外部配置元數據的進一步例子,bean定義可使用Spring的Groovy Bean Definition DSL(來自Grails框架)表示。通常的,這種配置保存在.groovy文件中並有以下的格式:

beans {
    dataSource(BasicDataSource) {
        driverClassName = "org.hsqldb.jdbcDriver"
        url = "jdbc:hsqldb:mem:grailsDB"
        username = "sa"
        password = ""
        settings = [mynew:"setting"]
    }
    sessionFactory(SessionFactory) {
        dataSource = dataSource
    }
    myService(MyService) {
        nestedBean = { AnotherBean bean ->
            dataSource = dataSource
        }
    }
}

這種配置風格在很大程度上等同於XML bean定義,甚至支持Spring XML配置的命名空間。它還容許經過「importBeans」指令導入XML bean定義文件。

3 使用容器

ApplicationContext是擁有註冊不一樣bean和它們之間依賴關係的高級工廠接口。使用方法 T getBean(String name, Class 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();

使用Groovy配置的啓動方式相似,僅僅是使用理解Groovy的context實現類(這個類依然可以識別XML的bean定義):

ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy");

最靈活的方式是將GenericApplicationContext類與reader代理一塊兒使用,例如讀取XML文件的XmlBeanDefinitionReader:

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

或者讀取Groovy文件的GroovyBeanDefinitionReader:

GenericApplicationContext context = new GenericApplicationContext();
new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy");
context.refresh();

若是須要這些reader代理能夠和同一ApplicationContext混合使用,從不一樣的配置源讀取bean定義。

可使用 getBean() 方法來獲取 bean 的實例。 ApplicationContext 接口有一些其餘的方法來獲取 bean,但理想的應用程序代碼不該該使用它們。事實上,你的應用程序代碼不該該調用的getBean() 方法,所以不會產生對 Spring 的 API 依賴性的。例如,Spring與web框架集成,爲web框架組件例如(controllers、JSF管理bean)提供依賴注入,容許你經過元數據爲特殊的bean聲明依賴關係。

相關文章
相關標籤/搜索