容器概述
The org.springframework.context.ApplicationContext
介面代表 Spring IoC 容器,負責例項化、配置和組裝 bean。容器透過讀取配置元資料來獲取例項化、配置和組裝元件的指令。配置元資料可以表示為帶註解的元件類、帶有工廠方法的配置類,或者外部 XML 檔案或 Groovy 指令碼。無論採用哪種格式,你都可以構建你的應用以及這些元件之間豐富的相互依賴關係。
ApplicationContext
介面的幾種實現在 Spring 核心中。在獨立應用中,通常建立 AnnotationConfigApplicationContext
或 ClassPathXmlApplicationContext
的例項。
在大多數應用場景中,不需要顯式使用者程式碼來例項化一個或多個 Spring IoC 容器例項。例如,在普通 Web 應用場景中,應用 web.xml
檔案中的簡單樣板 Web 描述符 XML 就足夠了(參閱 Web 應用的便捷 ApplicationContext 例項化)。在 Spring Boot 場景中,應用上下文會根據常見的設定約定為你隱式啟動。
下圖展示了 Spring 的高階工作檢視。您的應用類與配置元資料相結合,這樣在建立和初始化 ApplicationContext
後,您將擁有一個完全配置好的可執行系統或應用。

配置元資料
如前圖所示,Spring IoC 容器消費某種形式的配置元資料。這些配置元資料代表了您作為應用開發者如何告訴 Spring 容器例項化、配置和組裝應用中的元件。
Spring IoC 容器本身與配置元資料實際編寫的格式完全解耦。如今,許多開發者為他們的 Spring 應用選擇 基於 Java 的配置
-
基於註解的配置:使用應用元件類上的基於註解的配置元資料定義 bean。
-
基於 Java 的配置:使用基於 Java 的配置類在應用類外部定義 bean。要使用這些特性,請參閱
@Configuration
、@Bean
、@Import
和@DependsOn
註解。
Spring 配置至少包含一個(通常不止一個)由容器管理的 bean 定義。Java 配置通常在 @Configuration
類中使用 @Bean
註解的方法,每個方法對應一個 bean 定義。
這些 bean 定義對應於構成您應用的實際物件。通常,您會定義服務層物件、持久層物件(例如倉庫或資料訪問物件 (DAO))、表示層物件(例如 Web 控制器)、基礎設施物件(例如 JPA EntityManagerFactory
、JMS 佇列等)。通常,容器中不配置細粒度的領域物件,因為建立和載入領域物件通常是倉庫和業務邏輯的責任。
XML 作為外部配置 DSL
基於 XML 的配置元資料將這些 bean 配置為頂級 <beans/>
元素內的 <bean/>
元素。以下示例展示了基於 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="..."> (1) (2)
<!-- 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>
1 | id 屬性是一個字串,用於標識單個 bean 定義。 |
2 | class 屬性定義了 bean 的型別,使用完全限定類名。 |
id
屬性的值可用於引用協作物件。本示例未展示引用協作物件的 XML。有關更多資訊,請參閱依賴。
為了例項化容器,需要向 ClassPathXmlApplicationContext
建構函式提供 XML 資原始檔的位置路徑或多個路徑,該建構函式允許容器從各種外部資源(例如本地檔案系統、Java CLASSPATH
等)載入配置元資料。
-
Java
-
Kotlin
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
val context = ClassPathXmlApplicationContext("services.xml", "daos.xml")
學習 Spring 的 IoC 容器後,您可能想了解更多關於 Spring 的 |
以下示例展示了服務層物件 (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 檔案中會很有用。通常,每個單獨的 XML 配置檔案代表架構中的一個邏輯層或模組。
您可以使用 ClassPathXmlApplicationContext
建構函式從 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/>
元素)必須根據 Spring Schema 是有效的 XML bean 定義。
可以使用相對路徑 "../" 引用父目錄中的檔案,但不推薦這樣做。這樣做會建立對當前應用外部檔案的依賴。特別是,對於 您始終可以使用完全限定的資源位置而不是相對路徑:例如, |
名稱空間本身提供了匯入指令功能。Spring 提供的一系列 XML 名稱空間中提供了超出普通 bean 定義的更多配置特性 — 例如,context
和 util
名稱空間。
Groovy Bean 定義 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 定義檔案。
使用容器
The ApplicationContext
是一個高階工廠介面,能夠維護不同 bean 及其依賴項的登錄檔。透過使用方法 T getBean(String name, Class<T> requiredType)
,您可以檢索 bean 的例項。
The ApplicationContext
允許您讀取 bean 定義並訪問它們,如下例所示
-
Java
-
Kotlin
// 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();
import org.springframework.beans.factory.getBean
// create and configure beans
val context = ClassPathXmlApplicationContext("services.xml", "daos.xml")
// retrieve configured instance
val service = context.getBean<PetStoreService>("petStore")
// use configured instance
var userList = service.getUsernameList()
使用 Groovy 配置,啟動過程看起來非常相似。它有一個不同的上下文實現類,該類感知 Groovy(但也理解 XML bean 定義)。以下示例展示了 Groovy 配置
-
Java
-
Kotlin
ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy");
val context = GenericGroovyApplicationContext("services.groovy", "daos.groovy")
最靈活的變體是 GenericApplicationContext
結合讀者委託(reader delegates)— 例如,使用 XmlBeanDefinitionReader
處理 XML 檔案,如下例所示
-
Java
-
Kotlin
GenericApplicationContext context = new GenericApplicationContext();
new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml");
context.refresh();
val context = GenericApplicationContext()
XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml")
context.refresh()
您也可以對 Groovy 檔案使用 GroovyBeanDefinitionReader
,如下例所示
-
Java
-
Kotlin
GenericApplicationContext context = new GenericApplicationContext();
new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy");
context.refresh();
val context = GenericApplicationContext()
GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy")
context.refresh()
您可以在同一個 ApplicationContext
上混合和匹配這些讀者委託,從不同的配置源讀取 bean 定義。
然後,您可以使用 getBean
來檢索 bean 的例項。ApplicationContext
介面還有一些用於檢索 bean 的其他方法,但理想情況下,您的應用程式碼永遠不應使用它們。實際上,您的應用程式碼根本不應該呼叫 getBean()
方法,因此完全不依賴於 Spring API。例如,Spring 與 Web 框架的整合提供了對各種 Web 框架元件(如控制器和 JSF 管理的 bean)的依賴注入,允許您透過元資料(例如自動裝配註解)宣告對特定 bean 的依賴。