使用@Profile注解实现开发、测试和生产环境的配置和切换

导读:本篇文章讲解 使用@Profile注解实现开发、测试和生产环境的配置和切换,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

@Profile注解概述

在容器中如果存在同一类型的多个组件,那么可以使用@Profile注解标识要获取的是哪一个bean。也可以说@Profile注解是Spring为我们提供的可以根据当前环境,动态地激活和切换一系列组件的功能。这个功能在不同的环境使用不同的变量的情景下特别有用,例如,开发环境、测试环境、生产环境使用不同的数据源,在不改变代码的情况下,可以使用这个注解来动态地切换要连接的数据库。

接下来,我们来看下@Profile注解的源码,如下所示。
在这里插入图片描述
从其源码中我们可以得出如下三点结论:

@Profile注解不仅可以标注在方法上,也可以标注在配置类上。
如果@Profile注解标注在配置类上,那么只有是在指定的环境的时候,整个配置类里面的所有配置才会生效。
如果一个bean上没有使用@Profile注解进行标注,那么这个bean在任何环境下都会被注册到IOC容器中,当然了,前提是在整个配置类生效的情况下。
第一点很容易看出,勿须再说,后面两点如果你要是初次认识@Profile注解的话,那么是肯定看不出来的,这得通过我下面的讲解才能知道。

实战案例

接下来,我们就一起来看一个案例,即使用@Profile注解实现开发、测试和生产环境的配置和切换。这里,我们以开发过程中要用到的数据源为例(数据源也是一种组件哟😊)。我们希望在开发环境中,数据源是连向A数据库的;在测试环境中,数据源是连向B数据库的,而且在这一过程中,测试人员压根就不需要改动任何代码;最终项目上线之后,数据源连向C数据库,而且最重要的一点是在整个过程中,我们不希望改动大量的代码,而实现数据源的切换。

环境搭建

首先,我们需要在pom.xml文件中添加c3p0数据源和MySQL驱动的依赖,如下所示。

<dependency>
    <groupId>c3p0</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.1.2</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.44</version>
</dependency>

编写配置文件

因此,我们需要在项目的src/main/resources目录下新建一个配置文件,例如db.properties,在其中写上数据库连接的相关信息,如下所示。

db.driverClass=com.mysql.jdbc.Driver
db.username=root
db.password=root

在这里插入图片描述

添加完以上依赖之后,我们还得在项目中新建一个配置类,例如MainConfigOfProfile,并在该配置类中模拟开发、测试、生产环境的数据源,如下所示。

package com.baidu.bean;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.StringValueResolver;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

//@Profile("dev") // @Profile注解除了能写到bean上,还能写到类上
@PropertySource("classpath:/db.properties")//加载外部配置文件
//@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware {

    @Value("db.username")
    private String user;

    private StringValueResolver valueResolver;

    private String driverClass;

    //在测试环境被激活的情况下,测试环境下的所有bean都会被注册到IOC容器中
    //如果一个bean上没有使用@Profile注解进行标注,那么这个bean在任何环境下都会被注册到IOC容器中吗?hui
//    @Profile("test")
    @Bean
    public Yellow yellow(){
        return new Yellow();
    }


    @Profile("test")
    @Bean("dataSourceTest")
    public DataSource dataSourceTest(@Value("${db.password}") String password) throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();

        dataSource.setDriverClass(driverClass);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/profile");
        dataSource.setUser(user);
        dataSource.setPassword(password);

        return dataSource;
    }

    @Profile("default")
    @Bean("dataSourceDev")
    public DataSource dataSourceDev(@Value("${db.password}") String password) throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();

        dataSource.setDriverClass(driverClass);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/smbms");
        dataSource.setUser(user);
        dataSource.setPassword(password);

        return dataSource;
    }

    @Profile("pro")
    @Bean("dataSourcePro")
    public DataSource dataSourcePro(@Value("${db.password}") String password) throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();

        dataSource.setDriverClass(driverClass);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc");
        dataSource.setUser(user);
        dataSource.setPassword(password);

        return dataSource;
    }



    /**
     * Set the StringValueResolver to use for resolving embedded definition values.
     *
     * @param resolver
     */
    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.valueResolver = resolver;
        driverClass = valueResolver.resolveStringValue("${db.driverClass}");
    }
}

测试:

import com.baidu.bean.MainConfigOfProfile;
import com.baidu.bean.Yellow;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import javax.sql.DataSource;

public class IOCTest_Profile {

    @Test
    public void Test(){
        //1、使用一个无参构造器创建一个IOC容器
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        // 2. 在我们容器还没启动创建其他bean之前,先设置需要激活的环境(可以设置激活多个环境哟)
  		//可以设置我们所需要运行的环境
        context.getEnvironment().setActiveProfiles("test");
        // 3. 注册主配置类
        context.register(MainConfigOfProfile.class);
        // 4. 启动刷新容器
        context.refresh();


        String[] beanNamesForType = context.getBeanNamesForType(DataSource.class);
        for (String name : beanNamesForType) {
            System.out.println(name);
        }

        Yellow yellow = context.getBean(Yellow.class);
        System.out.println(yellow);

    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/71814.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!