`

Spring-Test:详解Spring中的Profile

阅读更多

转载:http://www.jianshu.com/p/948c303b2253

前言

由于在项目中使用Maven打包部署的时候,经常由于配置参数过多(比如Nginx服务器的信息、ZooKeeper的信息、数据库连接、Redis服务器地址等),导致实际现网的配置参数与测试服务器参数混淆,一旦在部署的时候某个参数忘记修改了,那么就必须重新打包部署,这确实让人感到非常头疼。因此就想到使用Spring中的Profile来解决上面描述的问题,并且在此记录一下其使用的方式,如果有不对的地方,请指正!(感谢)
本文从如下3方面探讨Spring的Profile:

  • Spring中的Profile是什么
  • 为什么要使用Profile
  • 如何使用Profile

1.Spring中的Profile 是什么?

Spring中的Profile功能其实早在Spring 3.1的版本就已经出来,它可以理解为我们在Spring容器中所定义的Bean的逻辑组名称,只有当这些Profile被激活的时候,才会将Profile中所对应的Bean注册到Spring容器中。举个更具体的例子,我们以前所定义的Bean,当Spring容器一启动的时候,就会一股脑的全部加载这些信息完成对Bean的创建;而使用了Profile之后,它会将Bean的定义进行更细粒度的划分,将这些定义的Bean划分为几个不同的组,当Spring容器加载配置信息的时候,首先查找激活的Profile,然后只会去加载被激活的组中所定义的Bean信息,而不被激活的Profile中所定义的Bean定义信息是不会加载用于创建Bean的。

2.为什么要使用Profile

由于我们平时在开发中,通常会出现在开发的时候使用一个开发数据库,测试的时候使用一个测试的数据库,而实际部署的时候需要一个数据库。以前的做法是将这些信息写在一个配置文件中,当我把代码部署到测试的环境中,将配置文件改成测试环境;当测试完成,项目需要部署到现网了,又要将配置信息改成现网的,真的好烦。。。而使用了Profile之后,我们就可以分别定义3个配置文件,一个用于开发、一个用户测试、一个用户生产,其分别对应于3个Profile。当在实际运行的时候,只需给定一个参数来激活对应的Profile即可,那么容器就会只加载激活后的配置文件,这样就可以大大省去我们修改配置信息而带来的烦恼。

3.配置Spring profile

在介绍完Profile以及为什么要使用它之后,下面让我们以一个例子来演示一下Profile的使用,这里还是使用传统的XML的方式来完成Bean的装配。

3.1 例子需要的Maven依赖

由于只是做一个简单演示,因此无需引入Spring其他模块中的内容,只需引入核心的4个模块+测试模块即可。

     <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--指定Spring版本,该版本必须大于等于3.1-->
        <spring.version>4.2.4.RELEASE</spring.version>
        <!--指定JDK编译环境-->
        <java.version>1.7</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${spring.version}</version>
        </dependency>


        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

3.2 例子代码

package com.panlingxiao.spring.profile.service;

/**
 * 定义接口,在实际中可能是一个数据源
 * 在开发的时候与实际部署的时候分别使用不同的实现
 */
public interface HelloService {

    public String sayHello();
}

定义生产环境使用的实现类

package com.panlingxiao.spring.profile.service.produce;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.panlingxiao.spring.profile.service.HelloService;

/**
 * 模拟在生产环境下需要使用的类
 */
@Component
public class ProduceHelloService implements HelloService {

    //这个值读取生产环境下的配置注入
    @Value("#{config.name}")
    private String name;

    public String sayHello() {
        return String.format("hello,I'm %s,this is a produce environment!",
                name);
    }
}

定义开发下使用的实现类

package com.panlingxiao.spring.profile.service.dev;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.panlingxiao.spring.profile.service.HelloService;

/**
 * 模拟在开发环境下使用类
 */
@Component
public class DevHelloService implements HelloService{

    //这个值是读取开发环境下的配置文件注入
    @Value("#{config.name}")
    private String name;

    public String sayHello() {
        return String.format("hello,I'm %s,this is a development environment!", name);
    }

}

定义配置Spring配置文件

<?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:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">

    <!-- 定义开发的profile -->
    <beans profile="development">
        <!-- 只扫描开发环境下使用的类 -->
        <context:component-scan base-package="com.panlingxiao.spring.profile.service.dev" />
        <!-- 加载开发使用的配置文件 -->
        <util:properties id="config" location="classpath:dev/config.properties"/>
    </beans>

    <!-- 定义生产使用的profile -->
    <beans profile="produce">
        <!-- 只扫描生产环境下使用的类 -->
        <context:component-scan
            base-package="com.panlingxiao.spring.profile.service.produce" />
        <!-- 加载生产使用的配置文件 -->    
        <util:properties id="config" location="classpath:produce/config.properties"/>
    </beans>
</beans>

开发使用的配置文件,dev/config.properties

    name=Tomcat

生产使用的配置文件,produce/config.properties

name=Jetty

编写测试类

package com.panlingxiao.spring.profile.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.panlingxiao.spring.profile.service.HelloService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="classpath:spring-profile.xml")
/*
 * 使用注册来完成对profile的激活,
 * 传入对应的profile名字即可,可以传入produce或者dev
 */
@ActiveProfiles("produce")
public class TestActiveProfile {

    @Autowired
    private HelloService hs;

    @Test
    public void testProfile() throws Exception {
        String value = hs.sayHello();
        System.out.println(value);
    }
}

激活dev运行结果.png

激活produce运行结果.jpg

4.激活Profile的其他几种方式

上面介绍了如何使用Profile以及在单元测试的环境下激活指定的Profile,除了使用@ActiveProfiles注解来激活profile外,Spring还提供了其他的几种激活Profile,这些方式在实际的开发中使用的更多。
Spring通过两个不同属性来决定哪些profile可以被激活(注意:profile是可以同时激活多个的),一个属性是spring.profiles.active和spring.profiles.default。这两个常量值在Spring的AbstractEnvironment中有定义,查看AbstractEnvironment源码:

    /**
     * Name of property to set to specify active profiles: {@value}. Value may be comma
     * delimited.
     * <p>Note that certain shell environments such as Bash disallow the use of the period
     * character in variable names. Assuming that Spring's {@link SystemEnvironmentPropertySource}
     * is in use, this property may be specified as an environment variable as
     * {@code SPRING_PROFILES_ACTIVE}.
     * @see ConfigurableEnvironment#setActiveProfiles
     */
    public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active";

    /**
     * Name of property to set to specify profiles active by default: {@value}. Value may
     * be comma delimited.
     * <p>Note that certain shell environments such as Bash disallow the use of the period
     * character in variable names. Assuming that Spring's {@link SystemEnvironmentPropertySource}
     * is in use, this property may be specified as an environment variable as
     * {@code SPRING_PROFILES_DEFAULT}.
     * @see ConfigurableEnvironment#setDefaultProfiles
     */
    public static final String DEFAULT_PROFILES_PROPERTY_NAME = "spring.profiles.default";

如果当spring.profiles.active属性被设置时,那么Spring会优先使用该属性对应值来激活Profile。当spring.profiles.active没有被设置时,那么Spring会根据spring.profiles.default属性的对应值来进行Profile进行激活。如果上面的两个属性都没有被设置,那么就不会有任务Profile被激活,只有定义在Profile之外的Bean才会被创建。我们发现这两个属性值其实是Spring容器中定义的属性,而我们在实际的开发中很少会直接操作Spring容器本身,所以如果要设置这两个属性,其实是需要定义在特殊的位置,让Spring容器自动去这些位置读取然后自动设置,这些位置主要为如下定义的地方:

  • 作为SpringMVC中的DispatcherServlet的初始化参数
  • 作为Web 应用上下文中的初始化参数
  • 作为JNDI的入口
  • 作为环境变量
  • 作为虚拟机的系统参数
  • 使用@AtivceProfile来进行激活

我们在实际的使用过程中,可以定义默认的profile为开发环境,当实际部署的时候,主需要在实际部署的环境服务器中将spring.profiles.active定义在环境变量中来让Spring自动读取当前环境下的配置信息,这样就可以很好的避免不同环境而频繁修改配置文件的麻烦。

参考:

  1. Spring Framework Reference Documentation 4.2.5.RELEASE-- 6.13. Environment abstraction
  2. Spring Framework Reference Documentation 3.2.3.RELEASE --3.2 Bean Definition Profiles
  3. <<Spring In Action Fourth Edition>>
分享到:
评论

相关推荐

    spring-beans-3.0.xsd

    《Spring框架中的beans配置文件详解——以spring-beans-3.0.xsd和3.1.xsd为例》 在Spring框架中,`spring-beans`是核心组件之一,它负责管理对象的生命周期和依赖关系。`spring-beans`的配置文件通常以`.xsd`为后缀...

    spring-mybatis-spring-2.1.0.zip

    《Spring与MyBatis整合详解及2.1.0版本应用》 在Java开发领域,Spring框架和MyBatis作为两个极为重要的组件,被广泛应用于企业级应用开发中。Spring以其强大的依赖注入(DI)和面向切面编程(AOP)能力,提供了全面...

    spring4.2.6 jar包

    《Spring框架4.2.6版本详解》 Spring框架,作为Java开发中的核心框架,以其模块化、松耦合的设计理念,为开发者提供了强大的企业级应用开发能力。本篇文章将聚焦于Spring框架的4.2.6版本,深入探讨其核心组件及应用...

    spring-framework-4.0.x

    - **配置优化**:避免过度配置,采用 Profiles 和 Profile-specific Beans 提高代码复用。 - **性能调优**:合理设置缓存策略,优化数据访问,减少内存泄漏。 - **安全考虑**:使用Spring Security增强应用安全性...

    SpringCloud配置详解

    - `spring.cloud.config.profile`: 应用的环境,如dev、test、prod。 这些配置参数只是SpringCloud庞大配置体系的一部分,每个组件都有丰富的可定制选项,根据实际项目需求进行调整。在实践中,通过合理的配置,...

    spring-boot-dynamic-datasource-started-master.rar

    2. `@Profile`:Spring Boot的环境配置注解,用于在不同环境中加载不同的配置。例如,我们可以设置一个开发环境数据源和生产环境数据源。 3. `application.properties`或`application.yml`:配置文件中,我们需要...

    2.SpringBoot运维实用篇(发布版).pdf

    ### Spring Boot运维实用篇知识点详解 #### 一、Spring Boot项目的打包与运行 **1.1 打包与运行概述** - **打包目的**: 将Spring Boot应用转换为可独立运行的格式,便于部署和分发。 - **运行方式**: 通过`java -...

    dev-sandbox:使用 Spring Boot 的项目配置沙箱

    **Spring Boot 项目配置沙箱详解** 在软件开发过程中,特别是在使用 Java 和 Spring Boot 框架时,创建一个良好的开发环境是至关重要的。"dev-sandbox" 是一个专为 Spring Boot 项目设计的配置沙箱,它允许开发者在...

    spring boot 案例

    ### Spring Boot 案例详解 #### 知识点一:Spring Boot 入门与启动配置 **描述:** Spring Boot 是一个简化 Spring 应用程序开发的框架,它简化了配置过程,允许开发者快速搭建应用程序。本章节将介绍如何使用 ...

    Maven管理SpringBoot Profile详解

    Maven 管理 Spring Boot Profile 详解 Maven 管理 Spring Boot Profile 是一个重要的知识点,它可以帮助开发者更好地管理 Spring Boot 项目中的配置文件和依赖关系。在本文中,我们将详细探讨 Maven 管理 Spring ...

    maven 入门到精通.txt

    - 可以在命令行中激活特定profile:`mvn clean install -P dev`。 3. **自动化构建**: - 配合持续集成工具(如Jenkins)实现自动化构建和部署。 - 支持版本控制系统的集成,如Git。 4. **发布到远程仓库**: ...

    Spring入门实战之Profile详解

    此外,Spring Boot进一步扩展了Profile的概念,它支持多环境配置文件,如`application.properties`、`application-dev.properties`、`application-test.properties`和`application-prod.properties`。这些文件根据...

    spring profile 多环境配置管理详解

    Spring Profile 是 Spring 框架中的一个重要特性,它允许开发者为不同的环境(如开发、测试、生产等)创建和管理独立的配置。在多环境配置管理中,Spring Profile 提供了方便的方式来切换不同环境下的配置,确保每个...

    Spring注解驱动开发.pdf

    ### Spring注解驱动开发知识点详解 #### 一、Spring注解驱动概述 Spring框架通过引入注解支持,极大地简化了Java EE应用的开发工作。它不仅提供了基础的依赖注入功能,还增强了对组件扫描的支持,使得开发者能够...

    spring dubbo maven 整合demo

    Spring Dubbo Maven 整合Demo详解 在现代的微服务架构中,Dubbo作为一个高性能、轻量级的服务治理框架,被广泛应用于分布式服务的构建。本教程将详细讲解如何使用Spring与Dubbo进行整合,以及如何通过Maven来管理...

    Java进阶之SpringIoC应用共18页.pdf.zi

    7. **Profile**:如何利用Spring的Profile功能来根据不同的环境条件激活不同的bean配置。 8. **Java配置**:对比XML配置,介绍使用@Configuration和@Bean注解进行Java配置的优势和用法。 9. **装配Bean**:讨论...

    spring4.0 Configuration的使用.docx

    ### Spring 4.0 中 @Configuration 的使用详解 #### 一、@Configuration 基础概念及使用场景 - **@Configuration** 注解自 Spring 3.0 引入,旨在提供一种基于 Java 的配置方式来替代传统的 XML 配置文件。通过...

    通过实例了解Spring中@Profile的作用

    Spring 中 @Profile 的作用详解 @Profile 是 Spring 框架中的一种注解,用于根据不同的环境来选择不同的配置或bean。通过使用 @Profile,可以根据不同的环境来选择不同的数据源、不同配置等。 @Profile 的作用主要...

    linux+jdk1.7 配置详解

    ### Linux + JDK 1.7 配置详解 #### 一、引言 在Linux环境下配置JDK 1.7是开发Java应用的基础步骤之一。本文将详细介绍如何在Linux操作系统中安装并配置JDK 1.7,确保开发环境能够正常运行Java程序。 #### 二、...

Global site tag (gtag.js) - Google Analytics