Spring環(huán)境與profile、條件化的bean(@condition)淺談
作者的話
對(duì)于不同的環(huán)境,代碼是有些差異的,開發(fā)環(huán)境、驗(yàn)證環(huán)境或者是生成環(huán)境,這就是需要用到profile來限定不同環(huán)境選擇初始化的bean是不同的,或者是滿足了某些條件才會(huì)去初始化特別的bean。
本篇文章主要談及到兩個(gè)知識(shí)點(diǎn),spring的profile和注解condition,也引入一下簡單的代碼來驗(yàn)證。
對(duì)于項(xiàng)目來說,一般開發(fā)是直接在開發(fā)環(huán)境dev進(jìn)行,如果沒有問題會(huì)在SIT(System Integration Testing)系統(tǒng)集成測試,再到UAT(User Acceptance Testing)用戶驗(yàn)收測試,最終上生產(chǎn),這些都是需要不同的數(shù)據(jù)庫或者是流程平臺(tái)等,不可能換個(gè)環(huán)境就手動(dòng)改很多代碼。
代碼示例
1、profile的使用
需要測試的bean,用于注入的spring
public class DemoBean {
?
private String content;
?
public DemoBean(String content) {
super();
this.content = content;
}
?
public String getContent() {
return content;
}
?
public void setContent(String content) {
this.content = content;
}
}
配置類,對(duì)于Bean可以是數(shù)據(jù)庫信息等的聲明
@Configuration
public class ProfileConfig {
?
/**
* Profile 為dev時(shí),實(shí)例化devDemoBean 開發(fā)環(huán)境
* @return
*/
@Bean
@Profile("dev")
public DemoBean devDemoBean() {
return new DemoBean("from development profile");
}
?
/**
* Profile 為prod時(shí),實(shí)例化prodDemoBean 生成環(huán)境
* @return
*/
@Bean
@Profile("prod")
public DemoBean prodDemoBean() {
return new DemoBean("from production profile");
}
}
測試程序入口
public class ProfileMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(ProfileConfig.class);
?
/**
* 1、先將活動(dòng)的profile設(shè)置為prod
* 2、后注冊(cè)Bean配置類,不然會(huì)報(bào)Bean未定義的錯(cuò)誤
* 3、刷新容器
*/
context.getEnvironment().setActiveProfiles("prod");
context.register(ProfileConfig.class);
context.refresh();
DemoBean demoBean = context.getBean(DemoBean.class);
?
System.out.println(demoBean.getContent());
?
context.close();
}
}
Profile 可以是不同環(huán)境有不同的配置,對(duì)于自己本地開發(fā)demo項(xiàng)目也是可以使用的,我之前開發(fā)一個(gè)項(xiàng)目時(shí),每次部署時(shí)都需要去改一下配置文件甚是著急,如果使用了profile,就會(huì)省去很多工作量。
2、Condition的使用
需要初始化類對(duì)于的接口
public interface ListService {
?
/**
* 不同操作系統(tǒng)環(huán)境下的命令
* @return 操作系統(tǒng)命令
*/
public String showListCmd();
}
接口對(duì)于的兩個(gè)類
public class WindowsListService implements ListService {
@Override
public String showListCmd() {
return "dir";
}
}
public class LinuxListService implements ListService {
@Override
public String showListCmd() {
return "ls";
}
}
根據(jù)添加創(chuàng)建的bean
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
?
/**
* @description: 判斷條件定義,判斷Windows的條件
*
* @author: Shenshuaihu
* @version: 1.0
* @data: 2019-05-30 23:12
*/
public class WindowsCondition implements Condition {
?
/**
* 如果返回的為True,改內(nèi)容會(huì)被創(chuàng)建
* @param conditionContext
* @param annotatedTypeMetadata
* @return
*/
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return conditionContext.getEnvironment().getProperty("os.name").contains("Windows");
}
}
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
?
/**
* @description: 判斷添加定義,判斷Linux的條件
*
* @author: Shenshuaihu
* @version: 1.0
* @data: 2019-05-30 23:15
*/
public class LinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
return conditionContext.getEnvironment().getProperty("os.name").contains("Linux");
}
}
核心配置類
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
?
/**
* @description: 配置類
* @author: Shenshuaihu
* @version: 1.0
* @data: 2019-05-30 23:20
*/
@Configuration
@ComponentScan("com.ch3.conditional")
public class ConditionConfig {
?
/**
* 通過 @Conditional 符號(hào)Windows條件則實(shí)例化 windowsListService
*
* @return
*/
@Bean
@Conditional(WindowsCondition.class)
public ListService windowsListService() {
return new WindowsListService();
}
?
@Bean
@Conditional(LinuxCondition.class)
public ListService linuxListService() {
return new LinuxListService();
}
}
測試啟動(dòng)類
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
?
/**
* @description:
* @author: Shenshuaihu
* @version: 1.0
* @data: 2019-05-30 23:22
*/
public class ConditionMain {
public static void main(String[] args) {
?
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(ConditionConfig.class);
?
ListService listService = context.getBean(ListService.class);
System.out.println(context.getEnvironment().getProperty("os.name")
+ " 系統(tǒng)下的列表命令為: "
+ listService.showListCmd()
);
}
}
對(duì)于LinuxCondition類 繼承了Condition,重寫matches方法,如果返回true則可以創(chuàng)建該類,可以是在不同的環(huán)境實(shí)現(xiàn)不同的方法,或者是當(dāng)存在什么屬性時(shí)則可以實(shí)例化,特定的方法。
使用場景就不贅述了,讀者可以自行配置使用。
參考相關(guān)的文章:
Spring profile 實(shí)現(xiàn)開發(fā),測試,部署等不同環(huán)境中間的配置切換【原創(chuàng)】
2019/6/1 晚 于成都