Spring 中如何根據(jù)環(huán)境切換配置 @Profile
Spring 根據(jù)環(huán)境切換配置 @Profile
我們實(shí)際開(kāi)發(fā)中往往有多個(gè)環(huán)境,比如測(cè)試環(huán)境、開(kāi)發(fā)環(huán)境、生產(chǎn)環(huán)境等;不同的環(huán)境往往配置也有區(qū)別,一直切換環(huán)境的配置很麻煩,Spring 為我們提供了一個(gè)注解,可以快速切換環(huán)境配置。
@Profile
我們新建一個(gè)配置,作用是注冊(cè)三個(gè)數(shù)據(jù)源,因?yàn)椴煌沫h(huán)境使用的數(shù)據(jù)庫(kù)一般不一樣:
@Configuration
@PropertySource("classpath:/person.properties")
public class MainConfigOfProfile implements EmbeddedValueResolverAware {
@Value("${db.user}")
private String user;
@Value("${db.url}")
private String url;
private String driver;
// 指定組件在那個(gè)環(huán)境下才能注冊(cè)到組件中: 不指定則都能注冊(cè)
@Profile("test")
@Bean("testDataSource")
public DataSource dataSourceTest(@Value("${db.password}") String pwd) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl(url);
dataSource.setDriverClass(driver);
return dataSource;
}
@Profile("dev")
@Bean("devDataSource")
public DataSource dataSourceDev(@Value("${db.password}") String pwd) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl(url);
dataSource.setDriverClass(driver);
return dataSource;
}
@Profile("prod")
@Bean("prodDataSource")
public DataSource dataSourceProd(@Value("${db.password}") String pwd) throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser(user);
dataSource.setPassword(pwd);
dataSource.setJdbcUrl(url);
dataSource.setDriverClass(driver);
return dataSource;
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.driver = resolver.resolveStringValue("${db.driver}");
}
}
這里在方法上使用了 @Profile 注解來(lái)表示對(duì)應(yīng)的環(huán)境,也就是說(shuō)當(dāng)指定環(huán)境之后,只有標(biāo)注對(duì)應(yīng)環(huán)境名的 Bean 才能被注冊(cè)到容器中去,沒(méi)有標(biāo)注任何 @Profile 的方法默認(rèn)直接注冊(cè)進(jìn)去。
環(huán)境區(qū)分好了如何啟動(dòng)對(duì)應(yīng)的環(huán)境?
有兩種方式:
- 使用命令行參數(shù);
- 使用無(wú)參構(gòu)造創(chuàng)建容器;
在 IDEA 中可以設(shè)置啟動(dòng)參數(shù),加上如下參數(shù):
-Dspring.profiles.active=test
其中 test 可以換成在 @Profile 中配置的名稱。

這樣就能指定環(huán)境啟動(dòng)了,還可以使用無(wú)參構(gòu)造創(chuàng)建容器。
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("prod", "dev");
context.register(MainConfigOfProfile.class);
context.refresh();
都是可以的,這里同時(shí)指定了兩個(gè)環(huán)境:prod 和 dev。
@Profile 也可以放在類上,這樣整個(gè)類就對(duì)應(yīng)指定的環(huán)境名。
在 IDEA 中,還可以使用圖形化界面快速切換所在的環(huán)境。

Spring配置profile,切換開(kāi)發(fā)環(huán)境和測(cè)試生產(chǎn)環(huán)境
項(xiàng)目的開(kāi)發(fā)環(huán)境和測(cè)試生產(chǎn)環(huán)境要配置的數(shù)據(jù)庫(kù),redis等等,連接地址都不一樣。這樣在項(xiàng)目部署到測(cè)試,生產(chǎn)時(shí)總要挨個(gè)修改這些配置。通過(guò)Spring的profile可以控制在不同的環(huán)境在Spring容器中注冊(cè)不同的配置Bean,然后用一個(gè)總開(kāi)關(guān)控制在什么環(huán)境用什么配置。
public interface CompactDisc {
void play();
}
有兩個(gè)類實(shí)現(xiàn)了它
public class MusicDisc implements CompactDisc {
private String music = "菊花臺(tái)";
/**
* @see com.xu.CompactDisc#play()
*/
@Override
public void play() {
System.out.println(music);
}
}
public class MovieDisc implements CompactDisc {
private String MovieConfig = "泰坦尼克號(hào)";
/**
* @see com.xu.CompactDisc#play()
*/
@Override
public void play() {
musicDisc.play();
}
}
基于java配置
@Configuration
public class MusicConfig {
@Bean
@Profile("dev")
public CompactDisc musicDisc(){
return new MusicDisc();
}
}
@Configuration
public class MovieConfig {
@Bean
@Profile("pro")
public CompactDisc movieDisc(){
return new MovieDisc();
}
}
@Controller
public class DiscController {
@Autowired(required=false)
private CompactDisc disc;
@RequestMapping("/disc")
public String disc(){
System.out.println("------進(jìn)入controller--------");
musicDisc.play();
return "ewr";
}
}
web.xml配置
<context-param>
<param-name>spring.profiles.default</param-name>
<param-value>dev</param-value>
</context-param>
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>pro</param-value>
</context-param>
<servlet>
<servlet-name>DispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/applicationContext.xml</param-value>
</init-param>
<init-param>
<param-name>spring.profiles.default</param-name>
<param-value>dev</param-value>
</init-param>
<load-on-startup> 1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Controller類里有一個(gè)CompactDisc 的注入,由于上面MovieDisc 和MusicDisc 都實(shí)現(xiàn)了CompactDisc ,那么在Spring容器啟動(dòng)是就要選擇一個(gè)注冊(cè),這個(gè)選擇是通過(guò)@Profile(“pro”)注解標(biāo)識(shí)的。然后通過(guò)在webxml里面添加spring.profiles.default控制
具體的控制規(guī)則如下:
xml里面配置了spring.profiles.default和spring.profiles.active,當(dāng)沒(méi)有active時(shí)默認(rèn)defalult中配置的dev,對(duì)應(yīng)配置類中@Profile(“dev”)標(biāo)識(shí)的MusicDisc會(huì)被創(chuàng)建;當(dāng)配置了active時(shí),@Profile(“dev”)會(huì)被創(chuàng)建。未被@Profile標(biāo)識(shí)的bean始終會(huì)被創(chuàng)建。所以根據(jù)上面的配置,當(dāng)訪問(wèn)http://localhost:8080/Spring/disc 時(shí)輸出是
------進(jìn)入controller--------
泰坦尼克號(hào)
這樣在部署不同的環(huán)境時(shí)通過(guò)控制spring.profiles.active和就ok了,而不必去一個(gè)一個(gè)的修改那些配置了。
xml配置方式
<beans profile="pro">
<bean id="compactDisc" class="com.xu.MusicDisc"></bean>
</beans>
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
如何優(yōu)雅的進(jìn)行Spring整合MongoDB詳解
這篇文章主要給大家介紹了如何優(yōu)雅的進(jìn)行Spring整合MongoDB的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-02-02
Resttemplate中設(shè)置超時(shí)時(shí)長(zhǎng)方式
這篇文章主要介紹了Resttemplate中設(shè)置超時(shí)時(shí)長(zhǎng)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
解決@RequestMapping和@FeignClient放在同一個(gè)接口上遇到的坑
這篇文章主要介紹了解決@RequestMapping和@FeignClient放在同一個(gè)接口上遇到的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
SpringBoot工程Docker多環(huán)境中使用同一個(gè)Jar包解決方案
在Docker多環(huán)境部署中,SpringBoot工程可以通過(guò)環(huán)境變量來(lái)動(dòng)態(tài)改變配置,無(wú)需重新打包,利用volume掛載或docker?cp命令,可以將配置文件直接傳入容器,提高部署效率,并保證安全性2024-09-09
Spring Bean初始化及銷毀多種實(shí)現(xiàn)方式
這篇文章主要介紹了Spring Bean初始化及銷毀多種實(shí)現(xiàn)方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
Java 使用Calendar計(jì)算時(shí)間的示例代碼
這篇文章主要介紹了Java 使用Calendar計(jì)算時(shí)間的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10

