1. 使用场景
在平常的开发工做中,咱们常常须要将程序部署到不一样的环境,好比Dev开发环境,QA测试环境,Prod生产环境,这些环境下的一些配置确定是不同的,好比数据库配置,Redis配置,RabbitMQ配置。
若是每次切换发布环境,都须要修改配置从新构建的话,那对程序员来讲将是噩梦,针对这种场景,Spring提供了@Profile注解来实现按照不一样的环境装配不一样的bean,进而实现程序只需构建一次,但能够部署到多个环境。
2. 配置profile bean
为了更好的理解,咱们经过具体的代码示例来理解下Spring profile的使用方法,这里咱们以数据库配置为例。
说明:本篇博客的重点是讲解@Profile注解的使用,数据库的操做只是辅助理解@Profile,所以不会讲解的太详细,不事后续会单独写博客讲解
假设咱们有3套环境(Dev,QA,Prod),这3套环境的数据库都使用的是mysql,可是其地址,用户名,密码都不同,那么在Java配置中,该如何声明这些bean呢?
2.1 Java配置中配置profile bean
首先须要了解的是,@Profile注解是从Spring 3.1版本中开始引入的,而且在这个版本中,@Profile注解只能在类级别上使用。
所以咱们能够按照环境分别建立数据库配置,以下所示:
Dev环境下的数据库配置:
package chapter03.profile;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import javax.sql.DataSource;
@Configuration
@Profile("dev")
public class DevDataSourceConfig {
@Bean
public DataSource devDataSource() {
System.out.println("This is dev DataSource");
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
basicDataSource.setUrl("jdbc:mysql://localhost:3306/mybatis_action_db");
basicDataSource.setUsername("dev");
basicDataSource.setPassword("dev");
return basicDataSource;
}
}
使用上述代码须要在pom.xml中添加以下依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.7.0</version>
</dependency>
注意事项:若是类级别上使用了@Profile("dev"),那么该类中的全部bean都会在profile为dev时建立。
QA环境下的数据库配置:
package chapter03.profile;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import javax.sql.DataSource;
@Configuration
@Profile("qa")
public class QADataSourceConfig {
@Bean
public DataSource qaDataSource() {
System.out.println("This is qa DataSource");
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
basicDataSource.setUrl("jdbc:mysql://localhost:3307/mybatis_action_db");
basicDataSource.setUsername("qa");
basicDataSource.setPassword("qa");
return basicDataSource;
}
}
Prod环境下的数据库配置:
package chapter03.profile;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import javax.sql.DataSource;
@Configuration
@Profile("prod")
public class ProdDataSourceConfig {
@Bean
public DataSource prodDataSource() {
System.out.println("This is prod DataSource");
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
basicDataSource.setUrl("jdbc:mysql://localhost:3308/mybatis_action_db");
basicDataSource.setUsername("prod");
basicDataSource.setPassword("prod");
return basicDataSource;
}
}
不过从Spring 3.2开始,@Profile注解能够与@Bean注解一块儿在方法级别上使用。
这也就使得咱们能够将刚刚的3个配置类合并成1个配置类(推荐该方式),以下所示:
package chapter03.profile;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
@Bean
@Profile("dev")
public DataSource devDataSource() {
System.out.println("This is dev DataSource");
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
basicDataSource.setUrl("jdbc:mysql://www.csyldl.com localhost:3306/mybatis_action_db");
basicDataSource.setUsername("dev");
basicDataSource.setPassword("dev");
return basicDataSource;
}
@Bean
@Profile("qa")
public DataSource qaDataSource() {
System.out.println("This is qa DataSource");
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
basicDataSource.setUrl("jdbc:mysql://localhost:3307/mybatis_action_db");
basicDataSource.setUsername(www.baiyiyulgw.com"qa");
basicDataSource.setPassword("qa");
return basicDataSource;
}
@Bean
@Profile("prod")
public DataSource prodDataSource() {
System.out.println("This is prod DataSource");
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.jdbc.Driver");
basicDataSource.setUrl("jdbc:mysql://localhost:3308/mybatis_action_db");
basicDataSource.setUsername("prod"www.yuchengyulegw.com);
basicDataSource.setPassword("prod");
return basicDataSource;
}
}
注意事项:没有指定profile的bean始终都会建立,与激活哪一个profile无关。
2.2 xml中配置profile bean
咱们也能够经过<beans>元素的profile属性,在xml中配置profile bean,以下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.fengshen157.com /schema/beans"
xmlns:xsi="http://www.jintianxuesha.com /2001/XMLSchema-instance"
xmlns:p="http://www.fengshen157.com /schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
profile="dev">
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/mybatis_action_db"
p:username="dev"
p:password="dev"/>
</beans>
能够参考该配置,分别建立qa和prod环境的profile xml文件。
不过仍是推荐使用嵌套的<beans>元素,在一个xml文件中配置好3个环境的数据源,代码以下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<beans profile="dev">
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/mybatis_action_db"
p:username="dev"
p:password="dev"/>
</beans>
<beans profile="qa">
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3307/mybatis_action_db"
p:username="qa"
p:password="qa"/>
</beans>
<beans profile="prod">
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3308/mybatis_action_db"
p:username="prod"
p:password="prod"/>
</beans>
</beans>
3. 激活profile
截止目前,咱们按照环境的维度建立了3个bean,但实际运行时,只会建立1个bean,具体建立哪一个bean取决于处于激活状态的是哪一个profile。
那么,咱们该如何激活某个profile呢?
Spring在肯定激活哪一个profile时,须要依赖2个属性:
spring.profiles.active
spring.profiles.default
spring.profiles.active的优先级比spring.profiles.default高,即若是没有配置spring.profiles.active,就使用spring.profiles.default配置的值,若是配置了spring.profiles.active,就不会再使用spring.profiles.default配置的值。
若是二者都没有配置,就只会建立那些没有定义profile的bean。
Web应用中,在web.xml中设置spring.profiles.active的代码以下所示:
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>dev</param-value>
</context-param>
也可使用代码方式激活:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("dev");
4. 单元测试
新建Main类,在其main()方法中添加以下测试代码:
package chapter03.profile;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.getEnvironment().setActiveProfiles("dev");
context.register(DataSourceConfig.class);
context.refresh();
context.close();
}
}
输出结果以下所示:
This is dev DataSource
若是将代码修改成context.getEnvironment().setActiveProfiles("qa");,输出结果为:
This is qa DataSource
若是将代码修改成context.getEnvironment().setActiveProfiles("prod");,输出结果为:
This is prod DataSourcejava