容器概覽
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 容器本身與此配置元資料實際編寫的格式完全解耦。如今,許多開發人員選擇 基於 Java 的配置 來構建他們的 Spring 應用程式。
-
基於註解的配置:在應用程式的元件類上使用基於註解的配置元資料定義 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"/>
<bean id="bean1" class="..."/>
<bean id="bean2" class="..."/>
</beans>
在前面的示例中,外部 bean 定義從檔案 services.xml 和 messageSource.xml 中載入。所有位置路徑都相對於執行匯入的定義檔案,因此 services.xml 必須與執行匯入的檔案位於同一目錄或類路徑位置,而 messageSource.xml 必須位於匯入檔案位置下的 resources 位置。如您所見,開頭的斜槓將被忽略。然而,考慮到這些路徑是相對的,最好根本不使用斜槓。被匯入檔案的內容,包括頂層 <beans/> 元素,必須是有效的 XML bean 定義,符合 Spring Schema。
|
可以(但不推薦)使用相對路徑 "../" 引用父目錄中的檔案。這樣做會建立一個對當前應用程式之外的檔案的依賴。特別地,對於 您可以始終使用完全限定的資源位置而不是相對路徑:例如, |
名稱空間本身提供了匯入指令功能。除了普通的 bean 定義之外,Spring 還提供了各種 XML 名稱空間中的更多配置功能,例如 context 和 util 名稱空間。
使用容器
ApplicationContext 是一個高階工廠的介面,它能夠維護不同 bean 及其依賴項的登錄檔。透過使用方法 T getBean(String name, Class<T> requiredType),您可以檢索您的 bean 例項。
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 與讀取器委託(例如,用於 XML 檔案的 XmlBeanDefinitionReader)結合使用,如下例所示
-
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()
您也可以將 GroovyBeanDefinitionReader 用於 Groovy 檔案,如下例所示
-
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 的依賴。