Spring源码从入门到精通---@Profile(十五)

上篇文章主要说了Aware接口:

如何吧spring底层组件赋值到自定义组件里呢,可以实现xxxAware接口,比如实现ApplicationContextAware接口,可以获取到applicationContext。这些都是由xxxAwareProcessor后置处理器处理的,如ApplicationContextAwareProcessor,先创建bean之后,后置处理器处理吧对应的数据赋值。

Aware&原理---Spring源码从入门到精通(十四)

这篇文章主要说@Profile:

文章分为两个部分,第一部分,数据源环境的搭建。第二部分,@Profile能根据开发环境和测试环境,家在不同的数据源,所有第二部分,如何通过spring提供的@Profile注解,根据我们当前的开发环境,动态的激活和切换一系列组件。

一、数据源环境搭建

先贴一份本文目录

首先创建myConfigProfile类,创建dataSource.properties配置文件,用我们之前学到过的@PropertySource注解指定加载的配置文件,用三种不同的方法获取到配置文件里面的值,都是我们之前学到过得。

1)、@Value普通获取值

2)、在方法参数上用@Value获取值

3)、实现EmbeddedValueResolverAware接口,解析器获取运行环境里面的值。

 配置文件如下:

dataName=root
dataPassword=root
data.driver.class=com.mysql.jdbc.Driver

新的配置类如下:


/**
 * @Profile:根据我们的当前环境,动态的激活和切换一系列组件。
 * 如test环境用test配置,dev环境用dev配置
 *
 * @author keying
 */
@PropertySource(value = {"classpath:/dataSources.properties"})
@Configuration
public class MyConfigProfile implements EmbeddedValueResolverAware {

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

    private String driverClass;

    @Bean("testDataSource")
    public DataSource test(@Value("${dataPassword}") String password) throws Exception {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setPassword(password);
        comboPooledDataSource.setUser(user);
        comboPooledDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/testmac");
        comboPooledDataSource.setDriverClass(driverClass);
        return comboPooledDataSource;
    }

    @Bean("devDataSource")
    public DataSource dev(@Value("${dataPassword}") String password) throws Exception {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setPassword(password);
        comboPooledDataSource.setUser(user);
        comboPooledDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/dev");
        comboPooledDataSource.setDriverClass(driverClass);
        return comboPooledDataSource;
    }

    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        //配置文件信息放入环境里,解析器从环境信息中获取
        this.driverClass = resolver.resolveStringValue("${data.driver.class}");
    }
}

/**
 * @author keying
 */
public class IOCTestProfile {

    @Test
    public void test() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(
            MyConfigProfile.class);
        //根据类型获取数据源
        String[] strings = applicationContext.getBeanNamesForType(DataSource.class);
        for(String string:strings){
            System.out.println(string);
        }
    }
}

通过junitTest打印可以看到,可以获取我们的两个数据源。本文演示是链接mysql数据库两个不同的database,同学请先在电脑上安装mysql数据库并建立好test和dev两个数据库,不知道安装mysql的自行百度。

 

二、@Profile注解使用

* 1、默认会加载@Profile("default"),指定组件在哪个环境才会注册到容器中,否则都不会注册到IOC容器。
* 2、改为加载test数据源:
* 1)使用命令行参数,在虚拟机参数位子加:-Dspring.profile.active=test
* 2)使用代码的方式,代码不能用有参构造器加载,从源码可以看到,配置类直接加载,就不能改系统环境里面的值。
* 用无参构造器refresh()容器,其实就是源码里的三步,第一步this()无参创建对象,第二部register注册配置类,第三部刷新创建容器。
* 3)没有配置@Profile的bean,不管在哪个环境都能加载。
*
* @Profile可以写在方法上,选择加载指定环境的配置组件。写在配置类上,只有满足当前环境,整个类才会加载。

/**
 * @author keying
 */
public class IOCTestProfile {

    /**
     * 1、默认会加载@Profile("default"),指定组件在哪个环境才会注册到容器中,否则都不会注册到IOC容器。
     * 2、改为加载test数据源:
     * 1)使用命令行参数,在虚拟机参数位子加:-Dspring.profile.active=test
     * 2)使用代码的方式,代码不能用有参构造器加载,从源码可以看到,配置类直接加载,就不能改系统环境里面的值。
     * 用无参构造器refresh()容器,其实就是源码里的三步,第一步this()无参创建对象,第二部register注册配置类,第三部刷新创建容器。
     * 3)没有配置@Profile的bean,不管在哪个环境都能加载。
     *
     * @Profile可以写在方法上,选择加载指定环境的配置组件。写在配置类上,只有满足当前环境,整个类才会加载。
     */
    @Test
    public void test() {
        //第一步创建applicationContext对象
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(
        );
        //第二部设置需要激活的环境
        ConfigurableEnvironment configurableEnvironment = applicationContext.getEnvironment();
        configurableEnvironment.setActiveProfiles("test");
        //第三部注册主配置类
        applicationContext.register(MyConfigProfile.class);
        //第四部刷新启动
        applicationContext.refresh();
        //根据类型获取数据源
        String[] strings = applicationContext.getBeanNamesForType(DataSource.class);
        for (String string : strings) {
            System.out.println(string);
        }

        Yellow yellow = applicationContext.getBean(Yellow.class);
        System.out.println(yellow);
        applicationContext.close();
    }
}

/**
 * @author keying
 * @Profile:根据我们的当前环境,动态的激活和切换一系列组件。 如test环境用test配置,dev环境用dev配置
 */
@PropertySource(value = {"classpath:/dataSources.properties"})
@Configuration
//@Profile("test")
public class MyConfigProfile implements EmbeddedValueResolverAware {

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

    private String driverClass;

    @Bean
    public Yellow yellow(){
        return new Yellow();
    }

    @Profile("test")
    @Bean("testDataSource")
    public DataSource test(@Value("${dataPassword}") String password) throws Exception {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setPassword(password);
        comboPooledDataSource.setUser(user);
        comboPooledDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/testmac");
        comboPooledDataSource.setDriverClass(driverClass);
        return comboPooledDataSource;
    }

    @Profile("dev")
    @Bean("devDataSource")
    public DataSource dev(@Value("${dataPassword}") String password) throws Exception {
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setPassword(password);
        comboPooledDataSource.setUser(user);
        comboPooledDataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/dev");
        comboPooledDataSource.setDriverClass(driverClass);
        return comboPooledDataSource;
    }

    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        //配置文件信息放入环境里,解析器从环境信息中获取
        this.driverClass = resolver.resolveStringValue("${data.driver.class}");
    }
}

从打印可以看出来,yellow在设置了test环境之后,还是 能打印出来,并且profile注解配置了dev的就打印不出来。

问:@Confitional注解和@Profile注解都能用在类上,并且都是不满足就不加载,有什么不同?

@Profile是修改系统环境的数据,需要在ioc容器refresh()之前设置,所以不能用有参构造加载配置类。

@Conditional则是在可以获取到环境里面的值,在进行过滤判断,如获取当前运行环境或者系统,进行过滤。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后端从入门到精通

你的鼓励是我最大的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值