零配置 之Spring基于Java类定义Bean配置元数据
轉載自??【第十二章】零配置 之 12.4 基于Java類定義Bean配置元數據 ——跟我學spring3?
12.4? 基于Java類定義Bean配置元數據
12.4.1? 概述
基于Java類定義Bean配置元數據,其實就是通過Java類定義Spring配置元數據,且直接消除XML配置文件。
基于Java類定義Bean配置元數據中的@Configuration注解的類等價于XML配置文件,@Bean注解的方法等價于XML配置文件中的Bean定義。
基于Java類定義Bean配置元數據需要通過AnnotationConfigApplicationContext加載配置類及初始化容器,類似于XML配置文件需要使用ClassPathXmlApplicationContext加載配置文件及初始化容器。
基于Java類定義Bean配置元數據需要CGLIB的支持,因此要保證類路徑中包括CGLIB的jar包。
?
12.4.2? Hello World
首先讓我們看一下基于Java類如何定義Bean配置元數據,具體步驟如下:
1、? 通過@Configuration注解需要作為配置的類,表示該類將定義Bean配置元數據;
2、? 通過@Bean注解相應的方法,該方法名默認就是Bean名,該方法返回值就是Bean對象;
3、? 通過AnnotationConfigApplicationContext或子類加載基于Java類的配置。
?
接下來讓我們先來學習一下如何通過Java類定義Bean配置元數據吧:
1、定義配置元數據的Java類如下所示:
package?cn.javass.spring.chapter12.configuration;?? import?org.springframework.context.annotation.Bean;?? import?org.springframework.context.annotation.Configuration;?? @Configuration??? public?class?ApplicationContextConfig?{??@Bean??public?String?message()?{??return?"hello";??}?? }?2、定義測試類,測試一下Java配置類是否工作:
package?cn.javass.spring.chapter12.configuration;?? //省略import?? public?class?ConfigurationTest?{??@Test??public?void?testHelloworld?()?{??AnnotationConfigApplicationContext?ctx?=?new?AnnotationConfigApplicationContext(ApplicationContextConfig.class);??Assert.assertEquals("hello",?ctx.getBean("message"));??}?? }??? ? 測試沒有報錯說明測試通過了,那AnnotationConfigApplicationContext是如何工作的呢,接下來讓我們分析一下:
- 使用@Configuration注解配置類,該配置類定義了Bean配置元數據;
- 使用@Bean注解配置類中的方法,該方法名就是Bean的名字,該方法返回值就是Bean對象。
- 使用new AnnotationConfigApplicationContext(ApplicationContextConfig.class)創建應用上下文,構造器參數為使用@Configuration注解的配置類,讀取配置類進行實例化相應的Bean。
知道如何使用了,接下來就詳細介紹每個部分吧。
?
12.4.3? @Configuration
通過@Configuration注解的類將被作為配置類使用,表示在該類中將定義Bean配置元數據,且使用@Configuration注解的類本身也是一個Bean,使用方式如下所示:
import?org.springframework.context.annotation.Configuration;?? @Configuration("ctxConfig")?? public?class?ApplicationContextConfig?{??//定義Bean配置元數據?? }???????? 因為使用@Configuration注解的類本身也是一個Bean,因為@Configuration被@Component注解了,因此@Configuration注解可以指定value屬性值,如“ctxConfig”就是該Bean的名字,如使用“ctx.getBean("ctxConfig")”將返回該Bean。
使用@Configuration注解的類不能是final的,且應該有一個默認無參構造器。
?
12.4.4? @Bean
通過@Bean注解配置類中的相應方法,則該方法名默認就是Bean名,該方法返回值就是Bean對象,并定義了Spring IoC容器如何實例化、自動裝配、初始化Bean邏輯,具體使用方法如下:
@Bean(name={},??autowire=Autowire.NO,??initMethod="",??destroyMethod="")??- name:指定Bean的名字,可有多個,第一個作為Id,其他作為別名;
- autowire:自動裝配,默認no表示不自動裝配該Bean,另外還有Autowire.BY_NAME表示根據名字自動裝配,Autowire.BY_TYPE表示根據類型自動裝配;
- initMethod和destroyMethod:指定Bean的初始化和銷毀方法。
示例如下所示(ApplicationContextConfig.java)
@Bean?? public?String?message()?{??return?new?String("hello");?? }??如上使用方式等價于如下基于XML配置方式
<bean?id="message"?class="java.lang.String">??<constructor-arg?index="0"?value="hello"/>?? </bean>??? ? 使用@Bean注解的方法不能是private、final或static的。
?
12.4.5? 提供更多的配置元數據
?????? 詳見【12.3.6? 提供更多的配置元數據】中介紹的各種注解,這些注解同樣適用于@Bean注解的方法。
?
12.4.6? 依賴注入
? 基于Java類配置方式的Bean依賴注入有如下兩種方式:
- 直接依賴注入,類似于基于XML配置方式中的顯示依賴注入;
- 使用注解實現Bean依賴注入:如@Autowired等等。
在本示例中我們將使用【第三章? DI】中的測試Bean。
1、?直接依賴注入:包括構造器注入和setter注入。
- 構造器注入:通過在@Bean注解的實例化方法中使用有參構造器實例化相應的Bean即可,如下所示(ApplicationContextConfig.java):
- setter注入:通過在@Bean注解的實例化方法中使用無參構造器實例化后,通過相應的setter方法注入即可,如下所示(ApplicationContextConfig.java):
2、使用注解實現Bean依賴注入:詳見【12.2? 注解實Bean依賴注入】。
??? 具體測試方法如下(ConfigurationTest.java):
@Test?? public?void?testDependencyInject()?{??AnnotationConfigApplicationContext?ctx?=?new?AnnotationConfigApplicationContext(ApplicationContextConfig.class);??ctx.getBean("helloImpl3",?HelloApi.class).sayHello();??ctx.getBean("helloImpl4",?HelloApi.class).sayHello();?? }???
12.4.7? 方法注入
在基于XML配置方式中,Spring支持查找方法注入和替換方法注入,但在基于Java配置方式中只支持查找方法注入,一般用于在一個單例Bean中注入一個原型Bean的情況,具體詳見【3.3.5? 方法注入】,如下所示(ApplicationContextConfig.java):
@Bean?? @Scope("singleton")?? public?HelloApi?helloApi2()?{??HelloImpl5?helloImpl5?=?new?HelloImpl5()?{??@Override??public?Printer?createPrototypePrinter()?{??//方法注入,注入原型Bean??return?prototypePrinter();??}??@Override??public?Printer?createSingletonPrinter()?{??//方法注入,注入單例Bean??return?singletonPrinter();??}??};??//依賴注入,注入單例Bean??helloImpl5.setPrinter(singletonPrinter());??return?helloImpl5;?? }?? @Bean?? @Scope(value="prototype")?? public?Printer?prototypePrinter()?{??return?new?Printer();??}?? @Bean?? @Scope(value="singleton")?? public?Printer?singletonPrinter()?{??return?new?Printer();?? }??具體測試方法如下(ConfigurationTest.java):
@Test?? public?void?testLookupMethodInject()?{??AnnotationConfigApplicationContext?ctx?=??new?AnnotationConfigApplicationContext(ApplicationContextConfig.class);??System.out.println("=======prototype?sayHello======");??HelloApi?helloApi2?=?ctx.getBean("helloApi2",?HelloApi.class);??helloApi2.sayHello();??helloApi2?=?ctx.getBean("helloApi2",?HelloApi.class);??helloApi2.sayHello();?? }??? ? 如上測試等價于【3.3.5? 方法注入】中的查找方法注入。
?
12.4.8? @Import
? 類似于基于XML配置中的<import/>,基于Java的配置方式提供了@Import來組合模塊化的配置類,使用方式如下所示:
package?cn.javass.spring.chapter12.configuration;?? //省略import?? @Configuration("ctxConfig2")?? @Import({ApplicationContextConfig.class})?? public?class?ApplicationContextConfig2?{??@Bean(name?=?{"message2"})??public?String?message()?{??return?"hello";??}?? }??具體測試方法如下(ConfigurationTest.java):
@Test?? public?void??importTest()?{??AnnotationConfigApplicationContext?ctx?=?new?AnnotationConfigApplicationContext(ApplicationContextConfig2.class);??Assert.assertEquals("hello",?ctx.getBean("message"));?? }??? ?使用非常簡單,在此就不多介紹了。
?
12.4.9? 結合基于Java和基于XML方式的配置
基于Java方式的配置方式不是為了完全替代基于XML方式的配置,兩者可以結合使用,因此可以有兩種結合使用方式:
- 在基于Java方式的配置類中引入基于XML方式的配置文件;
- 在基于XML方式的配置文件中中引入基于Java方式的配置。
?
一、在基于Java方式的配置類中引入基于XML方式的配置文件:在@Configuration注解的配置類上通過@ImportResource注解引入基于XML方式的配置文件,示例如下所示:
1、定義基于XML方式的配置文件(chapter12/configuration/importResource.xml):
<bean?id="message3"?class="java.lang.String">??<constructor-arg?index="0"?value="test"></constructor-arg>?? </bean>?2、修改基于Java方式的配置類ApplicationContextConfig,添加如下注解:
@Configuration("ctxConfig")?//1、使用@Configuration注解配置類?? @ImportResource("classpath:chapter12/configuration/importResource.xml")?? public?class?ApplicationContextConfig?{?? ……?? }??使用@ImportResource引入基于XML方式的配置文件,如果有多個請使用@ImportResource({"config1.xml", "config2.xml"})方式指定多個配置文件。
?
二、在基于XML方式的配置文件中中引入基于Java方式的配置:直接在XML配置文件中聲明使用@Configuration注解的配置類即可,示例如下所示:
1、定義基于Java方式的使用@Configuration注解的配置類在此我們使用ApplicationContextConfig.java。
2、定義基于XML方式的配置文件(chapter12/configuration/xml-config.xml):
<context:annotation-config/>?? <bean?id="ctxConfig"?class="cn.javass.spring.chapter12.configuration.ApplicationContextConfig"/>?? <context:annotation-config/>:用于開啟對注解驅動支持,詳見【12.2? 注解實現Bean依賴注入】; <bean id="ctxConfig" class="……"/>:直接將使用@Configuration注解的配置類在配置文件中進行Bean定義即可。3、測試代碼如下所示(ConfigurationTest.java)::
public?void?testXmlConfig()?{??String?configLocations[]?=?{"chapter12/configuration/xml-config.xml"};??ApplicationContext?ctx?=?new?ClassPathXmlApplicationContext(configLocations);??Assert.assertEquals("hello",?ctx.getBean("message"));?? }??測試成功,說明通過在基于XML方式的配置文件中能獲取到基于Java方式的配置文件中定義的Bean,如“message”Bean。
?
12.4.10? 基于Java方式的容器實例化
基于Java方式的容器由AnnotationConfigApplicationContext表示,其實例化方式主要有以下幾種:
一、對于只有一個@Configuration注解的配置類,可以使用如下方式初始化容器:
AnnotationConfigApplicationContext?ctx?=?new?AnnotationConfigApplicationContext(ApplicationContextConfig.class);?二、對于有多個@Configuration注解的配置類,可以使用如下方式初始化容器:
AnnotationConfigApplicationContext?ctx1?=?new?AnnotationConfigApplicationContext(ApplicationContextConfig.class,?ApplicationContextConfig2.class);??或者
AnnotationConfigApplicationContext?ctx2?=?new?AnnotationConfigApplicationContext();?? ctx2.register(ApplicationContextConfig.class);?? ctx2.register(ApplicationContextConfig2.class);???
三、對于【12.3??注解實現Bean定義】中通過掃描類路徑中的特殊注解類來自動注冊Bean定義,可以使用如下方式來實現:
public?void?testComponentScan()?{??AnnotationConfigApplicationContext?ctx?=?new?AnnotationConfigApplicationContext();??ctx.scan("cn.javass.chapter12.confiuration");??ctx.refresh();??Assert.assertEquals("hello",?ctx.getBean("message"));?? }??以上配置方式等價于基于XML方式中的如下配置:
<context:component-scan?base-package="cn.javass.chapter12.confiuration"/>???
四、在web環境中使用基于Java方式的配置,通過修改通用配置實現,詳見【10.1.2?通用配置】:
1、修改通用配置中的Web應用上下文實現,在此需要使用AnnotationConfigWebApplicationContext:
<context-param>??<param-name>contextClass</param-name>???????<param-value>??org.springframework.web.context.support.AnnotationConfigWebApplicationContext??</param-value>?? </context-param>?2、指定加載配置類,類似于指定加載文件位置,在基于Java方式中需要指定需要加載的配置類:
<context-param>??<param-name>contextConfigLocation</param-name>??<param-value>??cn.javass.spring.chapter12.configuration.ApplicationContextConfig,??cn.javass.spring.chapter12.configuration.ApplicationContextConfig2??</param-value>?? </context-param>??- contextConfigLocation:除了可以指定配置類,還可以指定“掃描的類路徑”,其加載步驟如下:
?1、首先驗證指定的配置是否是類,如果是則通過注冊配置類來完成Bean定義加載,即如通過ctx.register(ApplicationContextConfig.class)加載定義;
2、如果指定的配置不是類,則通過掃描類路徑方式加載注解Bean定義,即將通過ctx.scan("cn.javass.chapter12.confiuration")加載Bean定義。
?
總結
以上是生活随笔為你收集整理的零配置 之Spring基于Java类定义Bean配置元数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 9个最佳健身标识以及如何免费打造自己的[
- 下一篇: Java中CAS详解