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


    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. 源码及参考

    源码地址:https://github.com/zwwhnly/spring-action.git,欢迎下载。

    汪云飞《Java EE开发的颠覆者:Spring Boot实战》

    Craig Walls 《Spring实战(第4版)》

  • 相关阅读:
    过用户层HOOK思路
    Linux LVM实践
    matlab演奏卡农 Cripple Pachebel's Canon on Matlab
    rman备份恢复总结
    郁金香VC外挂教程(全) 翻录版 免Key(精品教程)
    C# string 中的 @ 作用处理\等字符
    (抓)2分法通用存储过程分页(top max模式)版本(性能相对之前的not in版本极大提高)
    怎样应用OracleParameter怎样写like查询语句?
    (转)DirectoryEntry的使用
    解决模式对话框和window.open打开新页面Session会丢失问题
  • 原文地址:https://www.cnblogs.com/zwwhnly/p/11350018.html
Copyright © 2020-2023  润新知