Spring⼊门实战之Profile详解
前⾔
Spring中的Profile功能其实早在Spring 3.1的版本就已经出来,它可以理解为我们在Spring容器中所定义的Bean的逻辑组名称,只有当这些Profile被激活的时候,才会将Profile中所对应的Bean注册到Spring容器中。
看到Profile这个关键字,或许你从来没有正眼瞧过他,⼜或者脑海中有些模糊的印象,⽐如除了这⾥Springmvc中的Profile,maven中也有Profile的标签。
从字⾯意思来看,Profile表⽰侧⾯,那什么情况下才会⽤到侧⾯这个功能呢,⽽侧⾯具体⼜有什么含义呢
打⼀个⽐⽅,对于数据库的配置问题,在开发的眼中可以使⽤嵌⼊的数据库,并且加载测试数据(后⾯会给出代码⽰例)。但是在测试的眼中,可能会配⼀个数据库连接池类似这样
@Bean(destroyMethod="close")
public DataSource dataSource () {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl("jdbc:h2:tcp://dbserver/~/test");
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUsername("sa");
dataSource.setPassword("password");
dataSource.setInitialSize(20);
dataSource.setMaxActive(30);
return dataSource;
}
当然还有产品环境下的配置等等。对于这种百花齐放的配置⽅式你还能说什么,默默的为这⼀套套的环境都部署相应的配置⽂件啊,没有profile这套我们⼀直都是这么做。
但是现在有了Profile,我们就多了⼀种选择,⼀种更加智能省⼼的配置⽅式。通过Profile配置,Spring可以在根据环境在运⾏阶段来决定bean的创建与否,先举例如下,主要从Profile bean的配置和激活来展开。
Profile bean的配置
通过注解@Profile配置
对于上⾯⽐⽅中的第⼀种情况,在开发环境中我们配置⼀个数据源可能是这样的
@Bean(destroyMethod = "shutdown")
public DataSource embeddedDataSource() {
return new EmbeddedDatabaseBuilder()
.addScript("classpath:schema.sql")
.addScript("classpath:test-data.sql")
.build();
}
这⾥会使⽤EmbeddedDatabaseBuilder创建⼀个嵌⼊式数据库,模式定义在类⽂件下的schema.sql⽂件中
schema.sql
create table Things (
id identity,
name varchar(100)
);
这⾥定义了⼀张Things表包含了两个字段
除了模式⽂件,还需要通过test-data.sql加载测试数据
test-data.sql
insert into Things (name) values ('A')
对于这个@Bean完全不知道是放在开发的环境下创建还是产品的环境下。所以我们这⾥可以使⽤注解@Profile帮助我们为这个bean打上标识。
从Spring 3.1版本中就引⼊了bean profile的功能,可以让你将不同的bean定义到⼀个或者多个profile⾥,然后在部署应⽤时告知要激活那个profile,则相应的bean就会被创建。
⽐如这⾥
@Configuration
@Profile("dev")
public class DevelopmentProfileConfig {
@Bean(destroyMethod = "shutdown")
public DataSource embeddedDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema.sql")
.addScript("classpath:test-data.sql")
.build();
}
}
通过@Profile("dev")为EmbedderDataSource bean标记为dev环境下要创建的bean。
注意:1. @Profile被加载类级别上,如果dev profile没有被激活,那么类中对应的所有bean就不会被创建
2. 如果当前是dev环境被激活了,那么对于没有使⽤@Profile的bean都会被创建,被标记为其他的profile如prod,则不会创建相应的bean
3. 从3.2开始@Profile不仅仅可以加载类级别上,还可以加载⽅法上,具体代码如下
app;
import javax.sql.DataSource;
import t.annotation.Bean;
import t.annotation.Configuration;
import t.annotation.Profile;
import org.springframework.bedded.EmbeddedDatabaseBuilder;
import org.springframework.bedded.EmbeddedDatabaseType;
import org.springframework.jndi.JndiObjectFactoryBean;
@Configuration
public class DataSourceConfig {
@Bean(destroyMethod = "shutdown")
@Profile("dev")
public DataSource embeddedDataSource() {
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema.sql")
.addScript("classpath:test-data.sql")
.build();
}
@Bean
@Profile("prod")
public DataSource jndiDataSource() {
JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
jndiObjectFactoryBean.setJndiName("jdbc/myDS");
jndiObjectFactoryBean.setResourceRef(true);
jndiObjectFactoryBean.setProxyInterface(javax.sql.DataSource.class);
return (DataSource) Object();
}
}
通过xml配置⽂件配置
除了简单的注解⽅式,我们哈可以通过在xml配置⽂件中声明的⽅式,具体配置如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="/schema/beans"
xmlns:xsi="/2001/XMLSchema-instance" xmlns:jdbc="/schema/jdbc"
xmlns:jee="/schema/jee" xmlns:p="/schema/p"
xsi:schemaLocation="
/schema/jee
/schema/jee/spring-jee.xsd
/schema/jdbc
/schema/jdbc/spring-jdbc.xsd
/schema/beans
/schema/beans/spring-beans.xsd">
<beans profile="dev">
<jdbc:embedded-database type="H2">
<jdbc:script location="classpath:schema.sql" />
<jdbc:script location="classpath:test-data.sql" />
</jdbc:embedded-database>
</beans>
<beans profile="prod">
<jee:jndi-lookup
lazy-init="true"
jndi-name="jdbc/myDatabase"
resource-ref="true"
proxy-interface="javax.sql.DataSource" />
</beans>
</beans>
这⾥分别声明了两种环境以及对应的profile。
profile激活
虽然我们已经配置好了profile,但是如何激活相应的环境呢。这⾥我们需要两个属性spring.profile.active以及spring.profile.default。
如果spring.profile.active被赋值了,则spring.profile.default就不会起作⽤,如果spring.profie.active没有赋值,则使⽤默认
的spring.profile.default设置的值。当然,如果两者都没有设置的话,则只会创建那些定义在相应的profile中的bean。
设置这两个属性的⽅式有很多:
作为DispactcherServlet的初始化参数
作为Web应⽤上下⽂参数
作为JNDI条⽬
作为环境变量
作为JVM的系统属性
在集成测试类上,使⽤@ActiveProfiles注解设置
⽐如我们在l中可以声明代码如下
<?xml version="1.0" encoding="UTF-8"?>
<web -app version="2.5"
...>
//为上下⽂设置默认的profile
<context-param>
<param-name>spring.profile.default</param-name>
<param-value>dev</param-value>
</context-param>
...
<servlet>
...
//为Serlvet设置默认的profile
<init-param>
<param-name>spring-profiles.default</param-name>
<param-value>dev</param-value>
</init-prama>
.
..
<web-app>
这样就可以指定需要启动那种环境,并准备相应的bean。
另外对于测试,spring为什么提供了⼀个简单的注解可以使⽤@ActiveProfiles,它可以指定运⾏测试的时候应该要激活那个profile。⽐如这⾥的测试类DevDataSourceTest
package profiles;
import static org.junit.Assert.*;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
springmvc常用标签import javax.sql.DataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.JdbcTemplate;
import org.RowMapper;
import st.context.ActiveProfiles;
import st.context.ContextConfiguration;
import st.context.junit4.SpringJUnit4ClassRunner;
app.DataSourceConfig;
public class DataSourceConfigTest {
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=DataSourceConfig.class)
@ActiveProfiles("dev")
public static class DevDataSourceTest {
@Autowired
private DataSource dataSource;
@Test
public void shouldBeEmbeddedDatasource() {
assertNotNull(dataSource);
JdbcTemplate jdbc = new JdbcTemplate(dataSource);
List<String> results = jdbc.query("select id, name from Things", new RowMapper<String>() { @Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
Long("id") + ":" + rs.getString("name");
}
});
assertEquals(1, results.size());
assertEquals("1:A", (0));
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes=DataSourceConfig.class)
@ActiveProfiles("prod")
public static class ProductionDataSourceTest {
@Autowired
private DataSource dataSource;
@Test
public void shouldBeEmbeddedDatasource() {
// should be null, because there isn't a datasource configured in JNDI
assertNull(dataSource);
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("l")
@ActiveProfiles("dev")
public static class DevDataSourceTest_XMLConfig {
@Autowired
private DataSource dataSource;
@Test
public void shouldBeEmbeddedDatasource() {
assertNotNull(dataSource);
JdbcTemplate jdbc = new JdbcTemplate(dataSource);
List<String> results = jdbc.query("select id, name from Things", new RowMapper<String>() { @Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
Long("id") + ":" + rs.getString("name");
}
});
assertEquals(1, results.size());
assertEquals("1:A", (0));
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("l")
@ActiveProfiles("prod")
public static class ProductionDataSourceTest_XMLConfig {
@Autowired(required=false)
private DataSource dataSource;
@Test
public void shouldBeEmbeddedDatasource() {
// should be null, because there isn't a datasource configured in JNDI
assertNull(dataSource);
}
}
}
运⾏shouldBeEmbeddedDatasource⽅法,测试通过
总结
以上就是这篇⽂章的全部内容了,希望本⽂的内容对⼤家的学习或者⼯作能带来⼀定的帮助,如果有疑问⼤家可以留⾔交流。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论