看到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 id="dataSource" 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 id="dataSource"
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方法,测试通过

  如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!如果您想持续关注我的文章,请扫描二维码,关注JackieZheng的微信公众号,我会将我的文章推送给您,并和您一起分享我日常阅读过的优质文章。

Spring实战——Profile的更多相关文章

  1. Spring实战6:利用Spring和JDBC访问数据库

    主要内容 定义Spring的数据访问支持 配置数据库资源 使用Spring提供的JDBC模板 写在前面:经过上一篇文章的学习,我们掌握了如何写web应用的控制器层,不过由于只定义了SpitterRep ...

  2. 《Spring实战》学习笔记-第五章:构建Spring web应用

    之前一直在看<Spring实战>第三版,看到第五章时发现很多东西已经过时被废弃了,于是现在开始读<Spring实战>第四版了,章节安排与之前不同了,里面应用的应该是最新的技术. ...

  3. Spring实战第六章学习笔记————渲染Web视图

    Spring实战第六章学习笔记----渲染Web视图 理解视图解析 在之前所编写的控制器方法都没有直接产生浏览器所需的HTML.这些方法只是将一些数据传入到模型中然后再将模型传递给一个用来渲染的视图. ...

  4. Spring实战第五章学习笔记————构建Spring Web应用程序

    Spring实战第五章学习笔记----构建Spring Web应用程序 Spring MVC基于模型-视图-控制器(Model-View-Controller)模式实现,它能够构建像Spring框架那 ...

  5. Spring实战读书笔记

    Spring实战读书笔记 Spring-core Spring之旅 - DI 和 AOP 概念 spring 的Bean容器 spring 的 核心模块 Spring的核心策略 POJO 最小侵入式编 ...

  6. Spring实战(第4版).pdf - 百度云资源

    http://www.supan.vip/spring%E5%AE%9E%E6%88%98 Spring实战(第4版).pdf 关于本书 Spring框架是以简化Java EE应用程序的开发为目标而创 ...

  7. 【译】Spring 4 @Profile注解示例

    前言 译文链接:http://websystique.com/spring/spring-profile-example/ 本文将探索Spring中的@Profile注解,可以实现不同环境(开发.测试 ...

  8. spring实战五之Bean的自动检测

    在spring实战四中,使用在Spring中增加<context:annotation-config>的方式告诉Spring,我们打算使用基于注解的自动装配,希望Spring特殊对待我们所 ...

  9. Spring实战——无需一行xml配置实现自动化注入

    已经想不起来上一次买技术相关的书是什么时候了,一直以来都习惯性的下载一份电子档看看.显然,如果不是基于强烈的需求或强大的动力鞭策下,大部分的书籍也都只是蜻蜓点水,浮光掠影. 就像有位同事说的一样,有些 ...

随机推荐

  1. 关于Discuz与jQuery冲突问题的亲测解决方法

    最近的一个项目整合dede和discuz程序,客户要求风格统一,所以有很多样式及特效都是要公用的.其中jQuery库定义的函数$()正好与discuz的comme.js中函数一样,这样就冲突了,导致d ...

  2. Nutch是个不错的选择

    对搜索引擎的理解:我们并没有google 的源代码,因此学习搜索引擎Nutch是个不错的选择.了解一个大型分布式的搜索引擎如何工作是一件让人很受益的事情.在写 Nutch的过程中,从学院派和工业派借鉴 ...

  3. 170113、CentOs6.4中安装和配置vsftp简明教程

    一.vsftp安装篇 代码如下: # 安装vsftpdyum -y install vsftpd# 启动service vsftpd start# 开启启动chkconfig vsftpd on 二. ...

  4. S3C2440的定时器详解

    还包含用于大电流驱动的死区发生器 位预分频器是可编程的,并且按存储在TCFG0和TCFG1寄存器中的加载值来分频PCLK 位递减计数器.当递减计数器到达零时,产生定时器中断请求通知CPU定时器操作已经 ...

  5. SD卡兼容性问题(转)

    看到一篇关于硬件抗干扰的应用实例,很有参考值.所以,转过来方便查找. 源文:SD卡兼容性问题 最近碰到了一个SD卡兼容性的问题.主芯片SD卡组的信号,经过转接板,长排线,然后再到SD卡子板之后.对多种 ...

  6. 苹果App Store开发者帐户从申请,验证,到发布应用(1)

    app store为开发者提供四种类型的申请: 个人ios开发者计划$99/年 公司ios开发者计划$99/年 企业ios开发者计划$299/年 高校ios开发者计划免费 在这里主要介绍一下公司ios ...

  7. C#生成随机验证吗例子

    C#生成随机验证吗例子: public class ValidateCode : IHttpHandler, IRequiresSessionState { HttpContext context; ...

  8. leetcode-005 reorder list

    1 package leetcode; public class ReOrderList { public void reorderList(ListNode head) { if(head==nul ...

  9. 蓝牙协议 基于TI cc2540 模块的理解(转)

    源:蓝牙协议 基于TI cc2540 模块的理解 Bluetooth 4.0开发 Platform:TI IC:cc2540 Environment:windows 7 tools:IAR 8.20. ...

  10. ubuntu内核的编译安装

    原创声明:转载请注明出处. 一.操作环境: 1.ubuntu版本 2.linux原有内核版本 3.要安装的linux内核版本 linux-3.16.39 二.新内核的编译和安装 1.首先下载linux ...