@Profile
很多情况下,我们的配置跟需要部署的环境是有关系的,比如我们的数据库连接地址、用户、密码等,各个环境是不一样的,即便我们通过配置文件加载,但不同的环境依然需要修改之后部署,通过@Profile注解可以将这些环境的配置分开,而且不用重复修改编码。
@Configuration
@Profile("development")
public class StandaloneDataConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.addScript("classpath:com/bank/config/sql/test-data.sql")
.build();
}
}
@Configuration
@Profile("production")
public class JndiDataConfig {
@Bean(destroyMethod="")
public DataSource dataSource() throws Exception {
Context ctx = new InitialContext();
return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}
}
默认配置文件
@Configuration
@Profile("default")
public class DefaultDataConfig {
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.HSQL)
.addScript("classpath:com/bank/config/sql/schema.sql")
.build();
}
}
以上是@Profile注释类的情况,@Profile还是注释方法
为了简化示例,我们来定义一个K类
package com.yyoo.boot.bean;
public class K {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package com.yyoo.boot.config;
import com.yyoo.boot.bean.K;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
@Profile("dev")
public class DevConfig {
@Bean
public K getK(){
return new K("开发环境");
}
}
package com.yyoo.boot.config;
import com.yyoo.boot.bean.K;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
@Configuration
@Profile("test")
public class TestConfig {
@Bean
public K getK(){
return new K("测试环境");
}
}
package com.yyoo.boot.annotation;
import com.yyoo.boot.bean.K;
import com.yyoo.boot.config.AppConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Demo11 {
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
K k = context.getBean(K.class);
System.out.println(k.getName());
}
}
如此执行后会报错,因为我们没有在程序中指定环境,我们也没有定义默认的profile。我们需要applicationContext的setActiveProfiles方法或者-Dspring.profiles.active来设置环境启动。
package com.yyoo.boot.annotation;
import com.yyoo.boot.bean.K;
import com.yyoo.boot.config.AppConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Demo11 {
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("dev");
context.register(AppConfig.class);
context.refresh();
K k = context.getBean(K.class);
System.out.println(k.getName());
}
}
@Import可以引入其他@Configuration类,来合并配置,最后只要注册对应的一个配置类即可
setActiveProfiles可以传入多个,但我们的逻辑就是其中一个就行了。如果我们加上dev和test一起,那咱们的@Profile就没有意义了。
注意写法,AppConfig需要使用register方法注册,而且最后需要refresh,否则都会报错。
关于@Profile我们先理解到这儿,后续我们Spring boot + maven的时候我们在来深入讲解@Profile与maven配置。(相关链接maven与spring的profile整合)
@Profile允许更复杂的逻辑判断
- !:配置文件的逻辑“非”
- &:配置文件的逻辑“与”
- |:配置文件的逻辑“或”
注意必要的情况下要是有小括号来保证你的逻辑正确。
Environment对象获取配置信息
package com.yyoo.boot.annotation;
import com.yyoo.boot.config.AppConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
public class Demo12 {
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
ConfigurableEnvironment environment = context.getEnvironment();
environment.setActiveProfiles("dev");
context.register(AppConfig.class);
context.refresh();
System.out.println(environment);
System.out.println(environment.getProperty("JAVA_HOME"));// 注意Key值的大小写
System.out.println(environment.getProperty("Path"));// 注意Key值的大小写
}
}
执行后你会发现我们程序中并无配置JAVA_HOME和Path,但能打印出来,因为我们在安装jdk的时候配置了对应的系统环境变量。
这意味着我们通过Environment类可以获取对应的系统配置
Environment继承结构图如下
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL9EFSlxGdtJGc412Y2plMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL0MDN5AzM1UTMzEzNwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
我们示例中实际上是StandardEnvironment。
StandardServletEnvironment,完整的层次结构如下
- ServletConfig 参数(如果适用 - 例如,在DispatcherServlet上下文的情况下)
- ServletContext 参数(web.xml 上下文参数条目)
- JNDI 环境变量(java:comp/env/条目)
- JVM 系统属性(-D命令行参数)
- JVM系统环境(操作系统环境变量)
使用@PropertySource添加自定义配置
package com.yyoo.boot.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;
@Configuration
@Import({DevConfig.class,TestConfig.class})
@PropertySource({"classpath:test.properties"})
public class AppConfig {
}
@PropertySource添加了一个resource目录的test.properties配置文件
配置文件
my.test.name = Hello Spring
JAVA_HOME = rewrite
修改K类如下
package com.yyoo.boot.bean;
import org.springframework.beans.factory.annotation.Value;
public class K {
private String name;
@Value("${JAVA_HOME}")
private String javaHome;
public K() {
}
public K(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getJavaHome() {
return javaHome;
}
public void setJavaHome(String javaHome) {
this.javaHome = javaHome;
}
}
@Value可以读取配置,但如果对应的key值不存在,项目启动将会报错。而且这个注解在任意类中可以使用,如果滥用对导致代码中有大量的@Value对应的key值,如果某个key值使用很多,当这个key值修改名称的时候就是个灾难。
@Value接收 , 占 位 符 , 执 行 时 会 替 换 为 响 应 k e y 对 应 的 值 , 如 果 不 是 有 {},占位符,执行时会替换为响应key对应的值,如果不是有 ,占位符,执行时会替换为响应key对应的值,如果不是有{},直接使用字符串,那么其注解的属性对应的值就是该字符串本身,这并没有什么意义。
Demo
package com.yyoo.boot.annotation;
import com.yyoo.boot.bean.K;
import com.yyoo.boot.config.AppConfig;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
public class Demo12 {
@Test
public void test(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
ConfigurableEnvironment environment = context.getEnvironment();
environment.setActiveProfiles("dev");
context.register(AppConfig.class);
context.refresh();
System.out.println(environment);
System.out.println(environment.getProperty("my.test.name"));
System.out.println(environment.getProperty("JAVA_HOME"));// 注意Key值的大小写
System.out.println(environment.getProperty("Path"));// 注意Key值的大小写
K k = context.getBean(K.class);
System.out.println(k.getJavaHome());
}
}
执行结果分析
执行后你会发现,自定义配置文件中my.test.name属性打印出来了,但自定义的JAVA_HOME并没有被覆盖。系统变量也能通过@Value注解注入到对应的bean中。
上一篇:007-Spring IoC 基于Java编程的配置
下一篇:009-Spring IoC 国际化(i18n)