欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Spring入门(七):Spring Profile使用讲解

程序员文章站 2022-06-24 08:51:44
1. 使用场景 在日常的开发工作中,我们经常需要将程序部署到不同的环境,比如Dev开发环境,QA测试环境,Prod生产环境,这些环境下的一些配置肯定是不一样的,比如数据库配置,Redis配置,RabbitMQ配置。 如果每次切换发布环境,都需要修改配置重新构建的话,那对程序员来说将是噩梦,针对这种场 ......

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://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("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");
        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.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"
       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个属性:

  1. spring.profiles.active
  2. 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 datasource

5. 源码及参考

源码地址:,欢迎下载。

汪云飞《java ee开发的颠覆者:spring boot实战》

craig walls 《spring实战(第4版)》

6. 最后

打个小广告,欢迎扫码关注微信公众号:「申城异乡人」,定期分享java技术干货,让我们一起进步。

Spring入门(七):Spring Profile使用讲解