Spring入门实战之Profile详解
来源:互联网 发布:小说哪个软件好 编辑:程序博客网 时间:2024/06/05 14:45
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不仅仅可以加载类级别上,还可以加载方法上,具体代码如下
package
com.myapp;
import
javax.sql.DataSource;
import
org.springframework.context.annotation.Bean;
import
org.springframework.context.annotation.Configuration;
import
org.springframework.context.annotation.Profile;
import
org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import
org.springframework.jdbc.datasource.embedded.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) jndiObjectFactoryBean.getObject();
}
}
通过xml配置文件配置
除了简单的注解方式,我们哈可以通过在xml配置文件中声明的方式,具体配置如下
datasource-config.xml
<?
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:jdbc
=
"http://www.springframework.org/schema/jdbc"
xmlns:jee
=
"http://www.springframework.org/schema/jee"
xmlns:p
=
"http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/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注解设置
比如我们在web.xml中可以声明代码如下
<?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;
import
javax.sql.DataSource;
import
org.junit.Test;
import
org.junit.runner.RunWith;
import
org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.jdbc.core.JdbcTemplate;
import
org.springframework.jdbc.core.RowMapper;
import
org.springframework.test.context.ActiveProfiles;
import
org.springframework.test.context.ContextConfiguration;
import
org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import
com.myapp.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 {
return
rs.getLong(
"id"
) +
":"
+ rs.getString(
"name"
);
}
});
assertEquals(
1
, results.size());
assertEquals(
"1:A"
, results.get(
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
(
"classpath:datasource-config.xml"
)
@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 {
return
rs.getLong(
"id"
) +
":"
+ rs.getString(
"name"
);
}
});
assertEquals(
1
, results.size());
assertEquals(
"1:A"
, results.get(
0
));
}
}
@RunWith
(SpringJUnit4ClassRunner.
class
)
@ContextConfiguration
(
"classpath:datasource-config.xml"
)
@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方法,测试通过
- Spring入门实战之Profile详解
- Spring实战笔记——Profile详解
- Spring Boot实战之入门
- Spring profile 详解
- 详解Spring中的Profile
- 详解Spring中的Profile
- 详解Spring中的Profile
- Spring profile 详解
- spring注解之@profile
- Spring3开发实战 之 第一章:Spring入门
- Spring3开发实战 之 第一章:Spring入门
- Maven之Profile详解
- Profile 详解之匿名用户 Profile 使用
- Spring 入门实战
- Profile 详解之 ProfileModule 类
- Oracle之用户Profile详解
- Spring框架总结之Profile使用
- spring oauth2.0入门(实战)
- java中的工厂方法模式(先把模板方法模式看透)
- JS正则表达式exec()与String.prototype.match()的差异
- opencv显示图像的傅里叶谱图像(频谱)源代码详解
- 十六、数组
- 格式化字符串
- Spring入门实战之Profile详解
- scroller原理
- c++ 类型转换const_cast<type id>(num);
- 文件操作
- Neutron总结-security group
- 使用Java读取Mysql的DateTime类型数据
- 代码与编程题
- [cocos2d-x]TextureCache和spriteFramecache
- 如何用Eclipse在Resin中调试Web应用程序