轉自:http://www.ibm.com/developerworks/cn/webservices/ws-springjava/
概述
眾所周知,Spring 架構是控制反轉 (IOC) 或依賴性注入 (DI) 模式的推動因素,而這種推動是通過基於容器的配置實現的。過去,Spring 允許開發人員使用基於 XML 的配置,通過利用應用程式上下文 XML 檔案來管理 bean 依賴性。此檔案處於應用程式的外部,包含 bean 及其與該應用程式的依賴項的定義。儘管使用 XML 配置較為簡單和便捷,但仍有另外一種方法可定義 bean 及其依賴項。這種方法也稱為基於 Java 的配置。不同於 XML,基於 Java 的配置使您能夠以編程方式管理 bean。這可通過運用多種注釋來實現。 這篇文章將示範 Java 配置樣本,並將其與傳統 XML 配置方法相對比。本文將按照如下步驟示範基於 Java 的配置的基本用法: 理解 @Configuration 和 @Bean 注釋 使用 AnnotationConfigApplicationContext 註冊配置類 配置 Web 應用程式 實現 bean 生命週期回調和範圍
我們將使用一所線上大學的 “建立課程” 用例。在建立課程的過程中,還會建立主題或者模組,而各主題可能又有著不同的作業。因此,我們要建立三個 bean,分別為 Course、Module 和 Assignment。Course bean 將包含一個對 Module bean 的引用,後者包含對 Assignment bean 的引用。 理解 @Configuration 和 @Bean 注釋
在理想的情境中,您可以在表示應用程式內容相關的 XML 中定義 bean。以下代碼展示了建立課程 用例中的上下文 XML 及 bean 定義: 清單 1. XML 與 bean 定義
<beans><bean id="course" class="demo.Course"><property name="module" ref="module"/> </bean><bean id="module" class="demo.Module"><property name="assignment" ref="assignment"/> </bean><bean id="assignment" class="demo.Assignment" /></beans>
以上 XML 就是您在使用 Spring 配置 bean 時通常會編寫的代碼。這段 XML 代碼定義了 Course bean,它引用 Module bean。Module bean 有一個 Assignment bean 的引用。您現在要刪除這段 XML,編寫同等效果的 Java 代碼。您將使用基於 Java 的配置定義上面指定的 bean。我們會將 XML 替換為 Java 類,這個 Java 類現在將用作 bean 配置的平台。我們將這個類命名為 AppContext.java。以下代碼展示了 AppContext類。 清單 2. 包含 bean 定義的 AppContext 配置類
@Configurationpublic class AppContext {@Beanpublic Course course() {Course course = new Course();course.setModule(module());return course;}@Beanpublic Module module() {Module module = new Module();module.setAssignment(assignment());return module;}@Beanpublic Assignment assignment() {return new Assignment();}}
正如您通過以上代碼所看到的那樣,現在可以以編程的方式將 bean 定義為基於 Java 的配置的一部分。AppContext 類現在就像 XML 一樣表示配置類。這是通過利用 @Configuration 注釋實現的。@Configuration 注釋位於類的頂端。它告知 Spring 容器這個類是一個擁有 bean 定義和依賴項的配置類。@Bean 注釋用於定義 bean。上述注釋位於執行個體化 bean 並設定依賴項的方法上方。方法名稱與 bean id 或預設名稱相同。該方法的傳回型別是向 Spring 應用程式上下文註冊的 bean。您可使用 bean 的 setter 方法來設定依賴項,容器將調用它們來串連相關項目。基於 Java 的配置也被視為基於注釋的配置。 使用 AnnotationConfigApplicationContext 註冊配置類
在傳統 XML 方法中,您可使用 ClassPathXmlApplicationContext 類來載入外部 XML 上下文檔案。但在使用基於 Java 的配置時,有一個AnnotationConfigApplicationContext 類。AnnotationConfigApplicationContext 類是 ApplicationContext 介面的一個實現,使您能夠註冊所注釋的配置類。此處的配置類是使用 @Configuration 注釋聲明的 AppContext。在註冊了所述類之後,@Bean 注釋的方法返回的所有 bean 類型也會得到註冊。以下代碼示範了 AnnotationConfigApplicationContext 類的使用: 清單 3. 使用 AnnotationConfigApplicationContext 註冊 AppContext 類
public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(AppContext.class); Course course = ctx.getBean(Course.class); course.getName();}
正如以上代碼所示,AppContext 配置類的註冊方式是將其傳遞給 AnnotationConfigApplicationContext 建構函式。此外,您還可以使用所述上下文類的 register 方法來註冊配置類。以下代碼展示了另外一種方法。 清單 4. 註冊 AppContext 類:另外一種方法
public static void main(String[] args) { ApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppContext.class)}
註冊配置類將自動註冊 @Bean 注釋的方法名稱,因而其對應的 bean 就是 Course、Module 和 Assignment。隨後您可以使用 getBean 方法來擷取相關的 bean,並調用其業務方法。如您所見,編寫 Java 的配置類並將其註冊到 Spring 上下文非常簡單。下一節將討論如何將基於 Java 的配置與 Web 應用程式配合使用。 配置 Web 應用程式
過去,您通常要利用 XmlWebApplicationContext 上下文來配置 Spring Web 應用程式,即在 Web 部署描述符檔案 web.xml 中指定外部 XML 上下文檔案的路徑。XMLWebApplicationContext 是 Web 應用程式使用的預設上下文類。以下代碼描述了 web.xml 中指向將由ContextLoaderListener 監聽器類載入的外部 XML 上下文檔案的元素。 清單 5. 使用外部 XML 上下文檔案的 web.xml
<web-app><context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><servlet><servlet-name>sampleServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class></servlet>...</web-app>
現在,您要將 web.xml 中的上述代碼更改為使用 AnnotationConfigApplicationContext 類。切記,XmlWebApplicationContext 是 Spring 為 Web 應用程式使用的預設上下文實現,因此您永遠不必在您的 web.xml 檔案中顯式指定這個上下文類。現在,您將使用基於 Java 的配置,因此在配置 Web 應用程式時,需要在 web.xml 檔案中指定 AnnotationConfigApplicationContext 類。上述代碼將修改如下: 清單 6. 修改後的使用 AnnotationConfigApplicationContext 的 web.xml
<web-app><context-param><param-name>contextClass</param-name><param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value></context-param><context-param><param-name>contextConfigLocation</param-name><param-value>demo.AppContext</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><servlet><servlet-name>sampleServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextClass</param-name><param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value></init-param></servlet>...</web-app>
以上修改後的 web.xml 現在定義了 AnnotationConfigWebApplicationContext 上下文類,並將其作為上下文參數和 servlet 元素的一部分。上下文配置位置現在指向 AppContext 配置類。這非常簡單。下一節將示範 bean 的生命週期回調和範圍的實現。 實現 bean 生命週期回調和範圍 生命週期回調
您還可以使用基於 Java 的配置來管理 bean 的生命週期。@Bean 支援兩種屬性,即 initMethod 和 destroyMethod,這些屬性可用於定義生命週期方法。在執行個體化 bean 或即將銷毀它時,容器便可調用生命週期方法。生命週期方法也稱為回調方法,因為它將由容器調用。使用 @Bean注釋註冊的 bean 也支援 JSR-250 規定的標準 @PostConstruct 和 @PreDestroy 注釋。如果您正在使用 XML 方法來定義 bean,那麼就應該使用 bean 元素來定義生命週期回調方法。以下代碼顯示了在 XML 配置中通常使用 bean 元素定義回調的方法。 清單 7. 使用 XML 方法實現生命週期回調
<bean id="course" class="demo.Course" init-method="setup" destroy-method="cleanup" ><property name="module" ref="module"/></bean>
以下代碼示範了使用 Java 配置的生命週期方法 清單 8. 使用 AppContext 配置類實現 bean 生命週期方法
@Configurationpublic class AppContext {@Bean(initMethod = "setup", destroyMethod = "cleanup")public Course course() {Course course = new Course();course.setModule(module());return course;}@Bean(initMethod = "setup", destroyMethod = "cleanup")public Module module() {Module module = new Module();module.setAssignment(assignment());return module;}...}public class Course {private Module module;private String name;public Course() {}public void setup() {this.name = "M100 Pythagoras Theorems"}public void setModule(Module module) {this.module = module;}public void cleanup() {module = null;}}
上面的代碼重新訪問了 AppContext 配置類。@Bean 注釋現在有兩個額外的屬性,即 initMethod 和 destroyMethod。它們定義了生命週期方法的設定和清除。這些方法是在已經註冊的 bean 中實現的,最終由容器在 bean 初始化及其銷毀之前調用它。這裡以 Course bean 為例,提供了生命週期方法實現。所實現的方法是 setup 和 cleanup。同樣,您還可以在 Module 和 Assignment bean 中實現這些方法。 Bean 範圍
bean 的方法是使用 @Scope 注釋定義的。XML 中實現這一目標的方法是指定 bean 元素中的 scope 屬性。 清單 9. 使用 XML 方法定義 bean 範圍
<bean id="course" class="demo.Course" scope="prototype" ><property name="module" ref="module"/></bean>