容器概覽

org.springframework.context.ApplicationContext 介面代表 Spring IoC 容器,負責例項化、配置和組裝 bean。容器透過讀取配置元資料來獲取有關要例項化、配置和組裝的元件的指令。配置元資料可以表示為帶註解的元件類、帶有工廠方法的配置類、外部 XML 檔案或 Groovy 指令碼。無論採用哪種格式,您都可以組合您的應用程式以及這些元件之間豐富的相互依賴關係。

ApplicationContext 介面的幾個實現是核心 Spring 的一部分。在獨立應用程式中,通常建立 AnnotationConfigApplicationContextClassPathXmlApplicationContext 的例項。

在大多數應用程式場景中,不需要顯式使用者程式碼來例項化一個或多個 Spring IoC 容器例項。例如,在普通 Web 應用程式場景中,應用程式的 web.xml 檔案中的簡單樣板 Web 描述符 XML 就足夠了(請參閱 Web 應用程式的便捷 ApplicationContext 例項化)。在 Spring Boot 場景中,應用程式上下文會根據常見的設定約定為您隱式引導。

下圖顯示了 Spring 工作原理的高階檢視。您的應用程式類與配置元資料結合,以便在 ApplicationContext 建立和初始化後,您擁有一個完全配置和可執行的系統或應用程式。

container magic
圖 1. Spring IoC 容器

配置元資料

如上圖所示,Spring IoC 容器使用某種形式的配置元資料。此配置元資料表示您作為應用程式開發人員如何告訴 Spring 容器例項化、配置和組裝應用程式中的元件。

Spring IoC 容器本身與此配置元資料實際編寫的格式完全解耦。如今,許多開發人員選擇 基於 Java 的配置 來構建他們的 Spring 應用程式。

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 的 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
		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 類和兩個 JpaAccountDaoJpaItemDao 型別的資料訪問物件(基於 JPA 物件關係對映標準)組成。property name 元素引用 JavaBean 屬性的名稱,ref 元素引用另一個 bean 定義的名稱。idref 元素之間的這種連結表達了協作物件之間的依賴關係。有關配置物件依賴關係的詳細資訊,請參閱 依賴關係

組合基於 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.xmlmessageSource.xml 中載入。所有位置路徑都相對於執行匯入的定義檔案,因此 services.xml 必須與執行匯入的檔案位於同一目錄或類路徑位置,而 messageSource.xml 必須位於匯入檔案位置下的 resources 位置。如您所見,開頭的斜槓將被忽略。然而,考慮到這些路徑是相對的,最好根本不使用斜槓。被匯入檔案的內容,包括頂層 <beans/> 元素,必須是有效的 XML bean 定義,符合 Spring Schema。

可以(但不推薦)使用相對路徑 "../" 引用父目錄中的檔案。這樣做會建立一個對當前應用程式之外的檔案的依賴。特別地,對於 classpath: URL(例如,classpath:../services.xml),不建議使用此引用,因為執行時解析過程會選擇“最近”的類路徑根,然後查詢其父目錄。類路徑配置更改可能導致選擇不同的、不正確的目錄。

您可以始終使用完全限定的資源位置而不是相對路徑:例如,file:C:/config/services.xmlclasspath:/config/services.xml。但是,請注意,您正在將應用程式的配置與特定的絕對位置耦合。通常更傾向於為這些絕對位置保留一個間接層——例如,透過在執行時針對 JVM 系統屬性解析的 "${...}" 佔位符。

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

使用容器

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 的依賴。

© . This site is unofficial and not affiliated with VMware.