接上篇:Spring 框架概述html
version 5.1.8.RELEASEjava
這部分參考文檔涵蓋了 Spring Framework 全部絕對不可或缺的技術。web
其中最重要的是 Spring Framework 的控制反轉(IoC)容器。在介紹完 Spring 框架的 IoC 容器以後,緊接着全面介紹 Spring 的面向切面編程(AOP)技術。Spring Framework 有本身的 AOP 框架,它在概念上易於理解,而且成功地定位了 Java 企業編程中 AOP 需求的 80% 最佳擊球點。spring
Spring 提供與 AspectJ (目前功能最豐富,也是Java企業領域中最成熟的 AOP 實現)的集成。sql
本章介紹 Spring 的控制反轉(IoC)容器。編程
本章介紹了 Spring Framework 控制反轉(IoC)的實現原理。IoC 也稱爲依賴注入(DI)。經過這個機制,對象能夠經過構造方法參數、工廠方法參數以及經過工廠方法構建或返回的實例上設置的屬性來定義它們的依賴關係(即它們使用的其餘對象)。而後容器在建立 bean 時注入這些依賴項。這個過程從根本上反轉了 Bean 自身經過直接調用構造方法或服務定位模式等機制來控制實例化或定位其依賴的模式,所以叫作控制反轉。api
org.springframework.beans
和 org.springframework.context
包是 Spring 框架的 IoC 容器的基礎。BeanFactory
接口提供了一種可以管理任何類型對象的高級配置機制。ApplicationContext
是 BeanFactory 的子類。它補充的內容有:session
簡而言之,BeanFactory
提供了配置框架和基本功能,ApplicationContext
添加了更多針對企業級的功能。ApplicationContext
是 BeanFactory
完整的超集,在本章中僅用它描述 Spring IoC 容器。有關使用 BeanFactory
而不是 ApplicationContext
的更多信息 請參考 BeanFactory。架構
在 Spring 中,構成應用程序架構並由 Spring IoC 容器管理的對象稱爲 beans。bean 是一個由 Spring IoC 容器實例化、組裝或管理的對象。除此以外,bean 只是應用程序中衆多對象之一。Bean 及其之間的依賴關係反映在容器使用的配置元數據中。app
org.springframework.context.ApplicationContext
接口表明 Spring IoC 容器,負責實例化、配置和組裝 bean。容器經過讀取配置元數據獲取有關須要實例化、配置和組裝對象的指令。配置元數據以 XML、Java 註解或 Java 代碼表示,經過它能夠表示構成應用的對象以及對象之間豐富的依賴關係。
Spring 提供了多種 ApplicationContext
接口實現。在傳統單機應用中,一般會建立一個 ClassPathXmlApplicationContext
或 FileSystemXmlApplicationContext
的實例。雖然 XML 是定義配置元數據的傳統格式,但你也能夠經過提供少許 XML 配置聲明容器啓用對其餘元數據格式的支持後使用 Java 註解或代碼做爲元數據格式。
在大多數應用程序方案中,不須要顯式使用代碼來實例化 Spring IoC 容器實例。例如,在 Web 應用程序場景中,應用程序文件 web.xml 中一個 8 行左右的 web 描述模板 XML 就足夠了(請參閱 Web 應用程序快速實例化 ApplicationContext)。若是你使用 Spring Tool Suite(一個基於 Eclipse 的開發環境),只需點擊幾下鼠標或按幾下鍵盤便可輕鬆建立此模板配置。
下圖是 Spring 工做原理的高級視圖。應用程序類與配置元數據相結合,在 ApplicationContext
建立並初始化以後,便可擁有徹底配置且可執行的系統或應用程序。
如上圖所示,Spring IoC 容器使用一系列配置元數據。這些配置元數據描述了Spring 容器在應用程序中如何實例化,配置和組裝對象。
傳統配置元數據使用簡單直觀的 XML 格式,本章大部份內容也是用 XML 來表達 Spring IoC 容器的關鍵概念和功能。
XML 不是惟一的配置元數據格式。Spring IoC 容器與實際編寫配置元數據的格式徹底解耦。目前,許多開發人員爲其 Spring 應用程序選擇基於 Java 的配置。
有關在 Spring 容器中使用其餘形式的元數據的信息,請參閱:
@Configuration
, @Bean
, @Import
,和 @DependsOn
註解。Spring 配置信息由至少一個(一般不止一個) 必須由容器進行管理的 bean 定義組成。基於 XML 的配置元數據將這些 bean 配置爲頂級元素 <beans/>
內的 <bean/>
元素。基於 Java 的配置一般在使用 @Configuration
註解的類中使用帶有 @Bean
註解的方法。
這些 bean 定義對應構成應用程序的實際對象。咱們通常會定義服務層對象,數據訪問對象(DAO),展現層對象(例如 Struts Action 實例),基礎結構對象(例如 Hibernate SessionFactories、JMS Queues 等)。通常不會在容器中配置細粒度的域對象,由於一般由 DAO 和業務邏輯負責建立和加載域對象。然而,你可使用 Spring 集成 AspectJ 來配置非 IoC 容器建立的對象。請參閱使用 Spring 和 AspectJ 進行域對象的依賴注入。
如下示例顯示了基於 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="...">①② <!-- 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。有關更多信息,請參閱依賴。
提供給 ApplicationContext 構造函數的位置路徑是一個資源字符串,它容許容器從各類外部資源加載配置元數據,例如本地文件系統、Java 環境變量等。
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
在瞭解了 Spring 的 IoC 容器以後,你可能想要了解有關 Spring
資源
抽象化(參考資源
描述)的更多信息,特別是Resource
路徑用於構建應用程序上下文(請參考應用程序上下文和資源路徑),它提供了一種便捷的機制從 URI 語句中定義的位置讀取 InputStream。。
如下示例展現了服務層對象配置文件(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"/> <!-- 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 https://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 文件中生效會很是有用。
如上一節中所示,應用程序上下文構造函數可使用多個 Resource 位置,它能夠從這些 XML 片斷中加載 bean 定義。另外也可使用一個或多個 <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 目錄中。正如你所見,前邊的斜槓會被忽略掉。鑑於提供的都是相對路徑,因此最好不要使用斜槓。這些文件中包括根據 Spring Schema 定義的正確的 XML Bean 在內的內容都會被導入,包括頂級元素 <beans/>
。
雖然可使用相對路徑「../」引用父目錄中的文件,但不建議這樣使用,由於這樣作會使得當前應用依賴程序以外的文件。很是不建議使用
classpath:
URL(例如,classpath:../services.xml)引用文件,由於運行時解析過程會選擇「最近」的環境變量根目錄,而後查找其父目錄。環境變量配置的更改可能致使目錄選擇不正確。可使用完整的資源位置替代相對路徑,例如,file:C:/config/services.xml 或 classpath:/config/services.xml。然而須要注意應用程序的配置將會與特定的絕對路徑耦合。一般最好爲這些絕對路徑保持間接聯繫,例如經過在運行時經過「$ {...}」佔位符替代 JVM 系統屬性。
命名空間自己提供了導入指令的功能。Spring 提供的一系列 XML 命名空間中提供了除普通 bean 定義以外的其餘配置功能,例如 context 和 util 命名空間。
做爲外化配置元數據的另外一個示例,bean 定義也能夠在 Spring 的 Groovy Bean 定義 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 定義文件。
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();
使用 Groovy 配置時,初始化程序看起來很是類似。不一樣的是使用了支持 Groovy 的上下文實現類(也支持 XML bean 定義)。如下示例展現了 Groovy 配置:
ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy");
最靈活的使用方式是 GenericApplicationContext
與讀取器委派結合使用,例如針對 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();
你能夠在相同的 ApplicationContext
中混合使用此類讀取器委託, 從不一樣的配置源讀取 bean 定義。
你可使用 getBean
方法來獲取 Bean 實例。ApplicationContext
接口還有一些其餘方法能夠獲取 bean,但理想狀況下你的應用程序不該該使用它們。實際上,你的應用程序代碼根本不該該調用 getBean()方法,也應該不依賴於 Spring API。例如,Spring 集成的 Web 框架爲各類 Web 框架組件(如控制器和 JSF 託管的 bean)提供依賴注入,以便經過元數據聲明對特定 bean 的依賴關係,例如自動裝配註解。