摘要
Spring4 以后,官方推薦我們使用Java Config來代替applicationContext.xml,聲明將Bean交給容器管理。
在Spring Boot中侥袜,Java Config的使用也已完全替代了applicationContext.xml。實現(xiàn)了xml的零配置溉贿。所以無論從Spring的演進枫吧,還是學(xué)習(xí)Spring Boot的需要,都應(yīng)該深入學(xué)習(xí)Spring Java Config的使用方法宇色。這篇文章主要從以下幾個方面進行介紹:
- Spring java Config 入門程序
- bean標簽的使用
- bean的依賴
- 自動掃描
- import 和 importResource
- properties文件的加載及占位
- profile
Spring Java Config入門介紹及簡單程序
回顧以前的applicationContext.xml配置方式九杂,我們會將需要使用bean通過xml的形式來配置,那么Java Config的方式宣蠕,不需要多思考例隆,就可以判斷我們應(yīng)該將bean配置在一個Java文件中,而且這個Java文件應(yīng)當(dāng)被Spring容器所識別抢蚀。我們看如下這個例子:
創(chuàng)建一個bean類
public class SomeBean {
public void doWork() {
System.out.println("do work...");
}
}
其中镀层,doWork
是邏輯方法。
創(chuàng)建一個Config類
@Configuration
public class Config {
@Bean
public SomeBean someBean() {
return new SomeBean();
}
}
需要注意的是皿曲,我們在config類上添加了一個@configuration
的注解唱逢,見名知意,我們可以理解為Spring中的配置類屋休。在返回值為SomeBean
的someBean
方法上我們添加了一個@Bean
注解坞古,也不難理解,返回的new SomeBean
對象將交由Spring容器進行管理劫樟。
測試
public class Test {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
SomeBean sb = context.getBean(SomeBean.class);
sb.doWork();
}
}
這里痪枫,我們創(chuàng)建了一個AnnotationConfigApplicationContext
對象,傳入了Config.class
后叠艳,得到了SomeBean對象奶陈。
do work...
以上就是Spring Java Config 配置bean的最簡單的程序,對不喜歡xml配置的開發(fā)人員還是比較有優(yōu)勢的附较。
我們知道尿瞭,在xml中,一般是這樣配置的:
<bean id="someBean" class="com.springboot.javaconfig.SomeBean" initMethod="init" destroyMethod="destroy" ref="otherBean" scope="singlon"
一個完整的bean配置包括了 id
,class
,initMethod
,destroyMethod
,·ref
,scope
翅睛。
那么声搁,在Java Config如何配置這些屬性呢?其實也是很簡單的捕发,我們修改第一個例子的代碼:
public class SomeBean {
private void init() {
System.out.println("init...");
}
public void doWork() {
System.out.println("do work...");
}
private void destroy() {
System.out.println("destroy...");
}
}
增加了init
,destroy
方法疏旨。
@Configuration
public class Config {
@Bean(initMethod = "init",destroyMethod = "destroy")
public SomeBean someBean() {
return new SomeBean();
}
}
在bean注解上,屬性指向?qū)?yīng)的方法名扎酷。
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
SomeBean sb1 = context.getBean(SomeBean.class);
System.out.println(sb1);
SomeBean sb2 = context.getBean(SomeBean.class);
System.out.println(sb2);
context.close();
}
}
輸出結(jié)果為:
init...
com.spring.SomeBean@16022d9d
com.spring.SomeBean@16022d9d
destroy...
從這個程序我們可以看出如下信息:
-
init
,destroy
方法都在相應(yīng)的階段被調(diào)用 - 兩次創(chuàng)建的SomeBean實例指向同一個地址檐涝,說明Spring容器給我們創(chuàng)建的SomeBean對象時單例的。
其它
如果希望創(chuàng)建了一個多例的bean,可以這樣書寫:
@Scope("prototype")
public class SomeBean {
}
如果希望使用id和class共同查找bean,可以這樣書寫:
SomeBean sb = context.getBean("someBean",SomeBean.class);
需要特別注意的是法挨,Spring默認使用Config中的函數(shù)名作為該bean的id谁榜。
bean的依賴
在xml中,我們使用value
來配置注入簡單值凡纳,ref
來配置注入其他對象窃植,那么在Java Config中如何實現(xiàn)呢?我們來繼續(xù)編寫代碼:
新建一個bean類
public class OtherBean {
}
修改SomeBean和Config類
public class SomeBean {
@Autowired
private OtherBean otherBean;
public void sayHello() {
System.out.println(otherBean);
}
}
@Configuration
public class Config {
@Bean
public SomeBean someBean() {
return new SomeBean;
}
@Bean
public OtherBean otherBean () {
return new OtherBean();
}
}
此時荐糜,我們將OtherBean
納入spring容器進行管理巷怜,在SomeBean
類中對OtherBean
的實例進行注入。得到結(jié)果:
com.spring.OtherBean@51b279c9
由此暴氏,實現(xiàn)了Java Config中的依賴注入延塑,只不過也就是將需要依賴的bean也加入Config
類用bean以修飾。
當(dāng)然答渔,我們也可以不使用@AutoWired
標簽关带,而通過set
方法注入。
@Configuration
public class Config {
@Bean
public SomeBean someBean(OtherBean otherBean) {
SomeBean someBean = new SomeBean();
// 1
someBean.setOtherBean(new OtherBean());
// 2
someBean.setOtherBean(otherBean());
// 3
someBean.setOtherBean(otherBean);
return someBean;
}
@Bean
public OtherBean otherBean () {
return new OtherBean();
}
}
set
注入方法比較多沼撕,可以自行創(chuàng)建一個OtherBean
對象宋雏,因為都在Config類中,也可以調(diào)用otherBean()
方法端朵,也可以在參數(shù)列表中進行傳入好芭,參數(shù)名要使用OtherBean
的方法名。因為OtherBean類型的可能有多個對象冲呢。
Java Config 和 注解配置混用
我們知道舍败,spring為我們提供了諸如@component
,@controller
,@service
,@repositroy
這類標簽,它們增加了類的語義敬拓,然后將對應(yīng)的類加入到了spring容器進行管理邻薯,也是避免了在xml中去配置。將Java Config和注解配置混用是我們在日常開發(fā)中經(jīng)常使用的方式乘凸,我們來看如下代碼厕诡,模擬MVC三層架構(gòu):
LoginDAO:
@Repository
public class LoginDAO {
public void login() {
System.out.println("login...");
}
}
LoginService
@Service
public class LoginService {
@Autowired
private LoginDao loginDao;
public void login() {
loginDao.login();
}
}
LoginController
@RequestMapping("/user")
@RestController
public class LoginController {
@Autowired
private LoginService loginService;
@RequestMapping(path = "/login",method = RequestMethod.POST)
public void login() {
loginService.login();
}
}
Java Config
@ComponentScan(basePackages = "com.spring")
@Configuration
public class Config {
}
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
LoginController controller = context.getBean("loginController",LoginController.class);
controller.login();
}
}
輸出結(jié)果:
login...
解讀:我們并沒有將LoginDAO
,LoginService
,LoginController
納入Config
,用@Bean
修飾,而是使用了注解配置营勤,在Config
類中通過ComponentScan
標簽灵嫌,將它們納入sping容器壹罚。通過測試, 我們發(fā)現(xiàn)寿羞,Java Config 和 注解配置的混合使用時可行的猖凛。
Java Config 和 applicationContext.xml混用
有時候,我們會遇到必須使用xml配置的情況绪穆,這時候辨泳,我們可以這樣來操作:
創(chuàng)建applicationContext.xml文件
<bean id="xmlBean" class="com.spring.XMLBean"/>
修改Config
@ImportResource("com/spring/applicationContext.xml")
@ComponentScan(basePackages = "com.spring")
@Configuration
public class Config {
}
運行結(jié)果:
com.spring.XMLBean@7bb58ca3
在Config
類上使用@ImportResource
標簽,就可以將在xml配置的bean引入到spring容器玖院。
占位符配置
自定義datasource
public class DataSource {
private String url;
private String driverClass;
private String userName;
private String password;
// get()
// set()
// constructor()
}
在xml中菠红,我們配置datasource
時往往將連接信息封裝在db.properties
中:
driverClass=com.mysql.jdbc.driver
url=jdbc:mysql://localhost:3306/my-database
username=root
password=root
在xml中使用占位的方式來獲取:
<context:property-placeholder location="com/spring/db.properties"/>
<bean id="dataSource" class="com.spring.DataSource">
<property name="url" value="${url}"/>
<property name="driverClass" value="${driverClass}"/>
<property name="userName" value="${user}"/>
<property name="password" value="${password}"/>
</bean>
測試
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
DataSource dataSource = context.getBean("dataSource",DataSource.class);
System.out.println(dataSource);
}
}
輸出結(jié)果:
DataSource{url='jdbc:mysql://localhost:3306/test', driverClass='com.mysql.jdbc.driver', userName='root', password='root'}
那么如何在Config中解讀占位配置呢难菌?繼續(xù)編寫代碼:
以示區(qū)分试溯,我們修改一下,db.properties:
driverClass=com.mysql.jdbc.driver
url=jdbc:mysql://localhost:3306/test
user=admin
password=admin
修改Config
//@ImportResource("com/spring/applicationContext.xml")
@PropertySource("com/spring/db.properties")
@ComponentScan(basePackages = "com.spring")
@Configuration
public class Config {
@Autowired
private Environment env;
@Bean
public DataSource dataSource() {
return new DataSource(env.getProperty("url"),env.getProperty("driverClass"),
env.getProperty("user"),env.getProperty("password"));
}
}
此時扔傅,我們先是去掉了@ImportResource
標簽耍共,因為已經(jīng)不需要在xml中配置了,又使用了一個新的標簽@PropertySource
猎塞,來加載db,properties
文件试读,然后又注入了一個env
對象,Environment
類繼承了PropertyResolver
接口荠耽,專門用來解析properties钩骇。
輸出結(jié)果:
DataSource{url='jdbc:mysql://localhost:3306/test', driverClass='com.mysql.jdbc.driver', user='admin', password='admin'}
可以看到,加載properties
文件铝量,在Spring Java Config也提供了支持倘屹。