从args讲到springboot全套配置体系架构(二)

回顾

在上文中讲到了系统的环境变量和属性,system.env和system.properties.这是java的两个全局变量。也就是说在java的应用程序中,你在任何为止都能取到其中的值。

并且我们可以通过set方法将(k,v)放到这两个全局变量中。
并且我们也知道了配置文件几乎可以从任何地方来,任何方式来,具体看自己的需求是什么样了。

那我们现在来看看spring 是不是将配置放到了这两个变量中呢?

二、Spring框架如何读取配置文件?

我们先来看一段程序

	@Autowired
    Environment environment;

    @Test
    public void contextLoads() {
System.out.println(System.getProperty("redis.host"));
        System.out.println(System.getenv("redis.host"));
        System.out.println(environment.getProperty("redis.host"));
    }

控制台输出结果

null
null
127.0.0.1

我们发现spring加载的配置文件并不会存到 System下的两个全局变量中,而是存到了一个 Environment 实例中。
那我们来看看 这个 Environment 是何方神圣,启动时加载默认配置以及系统配置。

Environment接口

Environment 这个接口可以说是贯穿了spring得全套源码体系。它继承了 PropertyResolver 所有加载得配置文件均在这个接口中。

包括System.getenv 和 System.getProperty 这两个全局变量也可以从这个接口中读取到。我们来实验下

@Autowired
    Environment environment;

    @Test
    public void contextLoads() {
   System.out.println(System.getProperty("redis.host"));
        System.out.println(System.getenv("redis.host"));
        System.out.println(environment.getProperty("redis.host"));
        System.out.println(environment.getProperty("USERNAME"));
    }

控制台输出

null
null
127.0.0.1
yaozhongjie

可以看到 USERNAME 这个是系统得变量,我们获取到了。
也就是说 spring得整个框架属性配置是围绕着 Environment 得接口来得。

我们打印了注入得类名发现实例化得是这个StandardEnvironment
下面是类图
在这里插入图片描述
项目启动时,先往把systemEnvironment 和systemProperties 放进了这个实例。当然还有 application 和 bootstrap 默认配置文件。
而自定义得配置文件是通过 Configuration注解或Component 注解
+propertySource 注解在bean初始化前后 进行加载得
AbstractApplicationContext.refresh() 方法中得invokeBeanFactoryPostProcessors(beanFactory);这一步进行初始化得。但是这个接口只提供了 取属性得方法,并未提供设置属性得方法哦。

StandardEnvironment类

	@Autowired
    Environment environment;
    @Autowired
    StandardEnvironment standardEnvironment;

    @Test
    public void contextLoads() {
		System.out.println(System.getProperty("redis.host"));
        System.out.println(System.getenv("redis.host"));
        System.out.println(environment.getProperty("redis.host"));
        System.out.println(environment.getProperty("USERNAME"));
        System.out.println(environment.getClass());
        System.out.println(environment);
        MutablePropertySources propertySources = standardEnvironment.getPropertySources();
        propertySources.forEach(System.out::println);
    }

控制台打印

null
null
127.0.0.1
yaozhongjie
class org.springframework.core.env.StandardEnvironment
StandardEnvironment {activeProfiles=[], defaultProfiles=[default], propertySources=[ConfigurationPropertySourcesPropertySource {name='configurationProperties'}, MapPropertySource {name='Inlined Test Properties'}, PropertiesPropertySource {name='systemProperties'}, OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}, RandomValuePropertySource {name='random'}, OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.properties]'}, ResourcePropertySource {name='class path resource [redis.properties]'}]}
ConfigurationPropertySourcesPropertySource {name='configurationProperties'}
MapPropertySource {name='Inlined Test Properties'}
PropertiesPropertySource {name='systemProperties'}
OriginAwareSystemEnvironmentPropertySource {name='systemEnvironment'}
RandomValuePropertySource {name='random'}
OriginTrackedMapPropertySource {name='applicationConfig: [classpath:/application.properties]'}
ResourcePropertySource {name='class path resource [redis.properties]'}

可以到这个实际上存储得是不同类型得文件对象。
ResourcePropertySource 为资源类型
OriginTrackedMapPropertySource 应用原始配置

那么这个时候问题来了,我如果写了两个一样得key,放在不同得配置文件下。那么用environment 中会读出哪个呢?
新建个 mq.properties

redis.host=123123123
redis.password=mq

新建配置类如下

@Configuration
@PropertySource(value = "classpath:mq.properties")
@ConfigurationProperties(prefix = "redis")
@Data
public class MqConfig {
    private String host;
    private String password;
    private int port;
}

测试类中打印

	@Autowired
    MqConfig mqConfig;

    @Autowired
    RedisConfig redisConfig;
    @Test
    public void contextLoads() {
        System.out.println(redisConfig.getHost());
        System.out.println(mqConfig.getHost());
    }

控制台输出

127.0.0.1
127.0.0.1

发现mqConfig 取到得也是redis.properties 中得值,那么我们怎么取到mq.properties中得值呢?
代码如下

MutablePropertySources propertySources = standardEnvironment.getPropertySources();
        String property = (String) propertySources.get("class path resource [mq.properties]").getProperty("redis.host");
        System.out.println(property);

控制台输出这样子就取到了。

123123123

当然现实开发中还是不要做如此愚蠢得事情。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值