Spring注解详解之自动注入(@Profile环境配置)

概述

@Profile注解是Spring提供的用来标注当前运行环境的注解,在我们实际工作过程中,会有多个环境,比如:开发环境,测试环境,和生产环境,在不同的环境中,配置会有所不同,比如数据源的配置,在不改动代码的情况下,可以使用@Profile注解来进行切换

源码

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {
	/**
	 * The set of profiles for which the annotated component should be registered.
	 */
	String[] value();

}

查看源码,该注解可以使用类上和方法上,使用在类上,表示只有在指定的环境下该类才会被注册,类中的方法才会执行

示例

进行三个数据源的配置,测试数据源,开发数据源,生产数据源

说明几点问题:

  • 加了@Profile注解指定了环境的bean,只有在该指定环境被激活时,才会被创建,默认是default环境,也即是不指定任何环境的情况下,就是@Profile(“default”)的配置
  • @Profile使用在类上时,只有在该指定环境被激活时,该类中的配置才会生效
  • 没有标注@Profile注解的bean,在任何环境下都是可以创建的
@Configuration
@PropertySource("classpath:/db.properties")
//@Profile("dev")
public class ProfileConfig implements EmbeddedValueResolverAware {

    @Value("${mysql.user}")
    private String user;

    private String driverClass;

    //@Profile("dev")开发环境数据源配置
    @Bean
    public DataSource dataSourceDev(@Value("${mysql.password}") String password) throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(password);
        dataSource.setDriverClass(driverClass);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/dev");
        return dataSource;
    }
    //@Profile("test")测试环境数据源配置
    @Bean
    public DataSource dataSourceTest(@Value("${mysql.password}") String password) throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(password);
        dataSource.setDriverClass(driverClass);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        return dataSource;
    }
    //@Profile("prod")生产环境数据源配置
    @Bean
    public DataSource dataSourceProd(@Value("${mysql.password}") String password) throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(password);
        dataSource.setDriverClass(driverClass);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/prod");
        return dataSource;
    }
    //@Profile("default")默认配置,
    @Bean
    public DataSource dataSourceDefault(@Value("${mysql.password}") String password) throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser(user);
        dataSource.setPassword(password);
        dataSource.setDriverClass(driverClass);
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/sys");
        return dataSource;
    }
	//通过EmbeddedValueResolverAware接口实现来解析配置数据
    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        String driverClass = resolver.resolveStringValue("${mysql.driver}");
        this.driverClass = driverClass;
    }
}

数据源配置文件

mysql.user=root
mysql.password=root
mysql.driver=com.mysql.jdbc.Driver

测试方法

@Test
public void testProfile() {
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ProfileConfig.class);
    //获取IOC容器中所有的DataSource类型的bean
    String[] names = applicationContext.getBeanNamesForType(DataSource.class);
    for (String name : names) {
        System.out.println(name);
    }
    applicationContext.close();
}
  • 放开方法上@Profile注解,不指定任何环境的情况下,运行输出结果为:dataSourceDefault,说明:不指定任何环境的情况下,是@Profile(“default”)的配置

  • 通过命令行的方式(-Dspring.profiles.active=dev),设置运行环境,此时运行输出结果为:dataSourceDev
    Spring注解详解之自动注入(@Profile环境配置)_第1张图片

  • 也可以通过代码的方式,设置激活的运行环境,输出结果为:dataSourceTest,dataSourceDev

@Test
public void testProfile() {
    //1.使用无参构造器创建对象
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
    //2.设置环境变量,激活test
    applicationContext.getEnvironment().setActiveProfiles("test","dev");
    //3.注册配置类
    applicationContext.register(ProfileConfig.class);
    //4.刷新容器
    applicationContext.refresh();
    String[] names = applicationContext.getBeanNamesForType(DataSource.class);
    for (String name : names) {
        System.out.println(name);
    }
    applicationContext.close();
}
  • 放开类上的@Profile(“dev”)的注释,设置激活test环境,则获取不到任何数据源对象,该配置类的所有配置都没执行

补充

上面提到了两种测试方法,一种是有参的构造方法,一种是无参的进行环境变量的初始化的,查看有参构造器的源码,两则的流程是一样的,只是使用无参的构造器,可以进行一些设置

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();//创建对象
    register(componentClasses);//注册配置类
    refresh();//刷新容器
}

你可能感兴趣的:(Spring注解详解之自动注入(@Profile环境配置))