# 【第十二章】零配置 之 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):
```
@Bean
public HelloApi helloImpl3() {
//通過構造器注入,分別是引用注入(message())和常量注入(1)
return new HelloImpl3(message(), 1); //測試Bean詳見【3.1.2 構造器注入】
}
```
* **setter注入**:通過在@Bean注解的實例化方法中使用無參構造器實例化后,通過相應的setter方法注入即可,如下所示(ApplicationContextConfig.java):
```
@Bean
public HelloApi helloImpl4() {
HelloImpl4 helloImpl4 = new HelloImpl4();//測試Bean詳見【3.1.3 setter注入】
//通過setter注入注入引用
helloImpl4.setMessage(message());
//通過setter注入注入常量
helloImpl4.setIndex(1);
return helloImpl4;
}
```
**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定義。
原創內容,轉載請注明私塾在線【[http://sishuok.com/forum/blogPost/list/0/2550.html](http://sishuok.com/forum/blogPost/list/0/2550.html#7325)】
- 跟我學 Spring3
- 【第二章】 IoC 之 2.1 IoC基礎 ——跟我學Spring3
- 【第二章】 IoC 之 2.2 IoC 容器基本原理 ——跟我學Spring3
- 【第二章】 IoC 之 2.3 IoC的配置使用——跟我學Spring3
- 【第三章】 DI 之 3.1 DI的配置使用 ——跟我學spring3
- 【第三章】 DI 之 3.2 循環依賴 ——跟我學spring3
- 【第三章】 DI 之 3.3 更多DI的知識 ——跟我學spring3
- 【第三章】 DI 之 3.4 Bean的作用域 ——跟我學spring3
- 【第四章】 資源 之 4.1 基礎知識 ——跟我學spring3
- 【第四章】 資源 之 4.2 內置Resource實現 ——跟我學spring3
- 【第四章】 資源 之 4.3 訪問Resource ——跟我學spring3
- 【第四章】 資源 之 4.4 Resource通配符路徑 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.1 概述 5.2 SpEL基礎 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.3 SpEL語法 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.4在Bean定義中使用EL—跟我學spring3
- 【第六章】 AOP 之 6.1 AOP基礎 ——跟我學spring3
- 【第六章】 AOP 之 6.2 AOP的HelloWorld ——跟我學spring3
- 【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.4 基于@AspectJ的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.5 AspectJ切入點語法詳解 ——跟我學spring3
- 【第六章】 AOP 之 6.6 通知參數 ——跟我學spring3
- 【第六章】 AOP 之 6.7 通知順序 ——跟我學spring3
- 【第六章】 AOP 之 6.8 切面實例化模型 ——跟我學spring3
- 【第六章】 AOP 之 6.9 代理機制 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.1 概述 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.2 JDBC模板類 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.3 關系數據庫操作對象化 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.4 Spring提供的其它幫助 ——跟我學spring3【私塾在線原創】
- 【第七章】 對JDBC的支持 之 7.5 集成Spring JDBC及最佳實踐 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.1 概述 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.2 集成Hibernate3 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.3 集成iBATIS ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.4 集成JPA ——跟我學spring3
- 【第九章】 Spring的事務 之 9.1 數據庫事務概述 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.2 事務管理器 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.3 編程式事務 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.4 聲明式事務 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.1 概述 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.2 集成Struts1.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.3 集成Struts2.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.4 集成JSF ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.1 概述 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.2 實現通用層 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.3 實現積分商城層 ——跟我學spring3
- 【第十二章】零配置 之 12.1 概述 ——跟我學spring3
- 【第十二章】零配置 之 12.2 注解實現Bean依賴注入 ——跟我學spring3
- 【第十二章】零配置 之 12.3 注解實現Bean定義 ——跟我學spring3
- 【第十二章】零配置 之 12.4 基于Java類定義Bean配置元數據 ——跟我學spring3
- 【第十二章】零配置 之 12.5 綜合示例-積分商城 ——跟我學spring3
- 【第十三章】 測試 之 13.1 概述 13.2 單元測試 ——跟我學spring3
- 【第十三章】 測試 之 13.3 集成測試 ——跟我學spring3
- 跟我學 Spring MVC
- SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常見問題總結
- Spring Web MVC中的頁面緩存支持 ——跟我學SpringMVC系列
- Spring3 Web MVC下的數據類型轉換(第一篇)——《跟我學Spring3 Web MVC》搶先看
- Spring3 Web MVC下的數據格式化(第二篇)——《跟我學Spring3 Web MVC》搶先看
- 第一章 Web MVC簡介 —— 跟開濤學SpringMVC
- 第二章 Spring MVC入門 —— 跟開濤學SpringMVC
- 第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC
- 第四章 Controller接口控制器詳解(1)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(2)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解 (4)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(5)——跟著開濤學SpringMVC
- 跟著開濤學SpringMVC 第一章源代碼下載
- 第二章 Spring MVC入門 源代碼下載
- 第四章 Controller接口控制器詳解 源代碼下載
- 第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(7 完)——跟著開濤學SpringMVC
- 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 源代碼下載 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 注解式控制器運行流程及處理器定義 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- 源代碼下載 第六章 注解式控制器詳解
- SpringMVC3強大的請求映射規則詳解 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- Spring MVC 3.1新特性 生產者、消費者請求限定 —— 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(1)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(2)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC數據類型轉換——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據格式化——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據驗證——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC