Spring 中如何根据环境切换配置 @Profile
作者:硕子鸽
Spring 根据环境切换配置 @Profile
我们实际开发中往往有多个环境,比如测试环境、开发环境、生产环境等;不同的环境往往配置也有区别,一直切换环境的配置很麻烦,Spring 为我们提供了一个注解,可以快速切换环境配置。
@Profile
我们新建一个配置,作用是注册三个数据源,因为不同的环境使用的数据库一般不一样:
@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; // 指定组件在那个环境下才能注册到组件中: 不指定则都能注册 @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 注解来表示对应的环境,也就是说当指定环境之后,只有标注对应环境名的 Bean 才能被注册到容器中去,没有标注任何 @Profile 的方法默认直接注册进去。
环境区分好了如何启动对应的环境?
有两种方式:
- 使用命令行参数;
- 使用无参构造创建容器;
在 IDEA 中可以设置启动参数,加上如下参数:
-Dspring.profiles.active=test
其中 test 可以换成在 @Profile 中配置的名称。
这样就能指定环境启动了,还可以使用无参构造创建容器。
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); context.getEnvironment().setActiveProfiles("prod", "dev"); context.register(MainConfigOfProfile.class); context.refresh();
都是可以的,这里同时指定了两个环境:prod 和 dev。
@Profile 也可以放在类上,这样整个类就对应指定的环境名。
在 IDEA 中,还可以使用图形化界面快速切换所在的环境。
Spring配置profile,切换开发环境和测试生产环境
项目的开发环境和测试生产环境要配置的数据库,redis等等,连接地址都不一样。这样在项目部署到测试,生产时总要挨个修改这些配置。通过Spring的profile可以控制在不同的环境在Spring容器中注册不同的配置Bean,然后用一个总开关控制在什么环境用什么配置。
public interface CompactDisc { void play(); }
有两个类实现了它
public class MusicDisc implements CompactDisc { private String music = "菊花台"; /** * @see com.xu.CompactDisc#play() */ @Override public void play() { System.out.println(music); } } public class MovieDisc implements CompactDisc { private String MovieConfig = "泰坦尼克号"; /** * @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("------进入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类里有一个CompactDisc 的注入,由于上面MovieDisc 和MusicDisc 都实现了CompactDisc ,那么在Spring容器启动是就要选择一个注册,这个选择是通过@Profile(“pro”)注解标识的。然后通过在webxml里面添加spring.profiles.default控制
具体的控制规则如下:
xml里面配置了spring.profiles.default和spring.profiles.active,当没有active时默认defalult中配置的dev,对应配置类中@Profile(“dev”)标识的MusicDisc会被创建;当配置了active时,@Profile(“dev”)会被创建。未被@Profile标识的bean始终会被创建。所以根据上面的配置,当访问http://localhost:8080/Spring/disc 时输出是
------进入controller--------
泰坦尼克号
这样在部署不同的环境时通过控制spring.profiles.active和就ok了,而不必去一个一个的修改那些配置了。
xml配置方式
<beans profile="pro"> <bean id="compactDisc" class="com.xu.MusicDisc"></bean> </beans>
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。