Environment的中文意思是环境,它示意整个spring利用运行时的环境信息,它蕴含两个关键因素

  • profiles
  • properties

profiles

profiles这个概念置信大家都曾经了解了,最常见的就是不同环境下,决定以后spring容器中的不同配置上下文的解决方案。比方针对开发环境、测试环境、生产环境,构建不同的application.properties配置项,这个时候咱们能够通过profiles这个属性来决定以后spring利用上下文中失效的配置项。

实际上,通过profiles能够针对bean的配置进行逻辑分组。 简略来说,咱们能够通过profiles来针对不同的bean进行逻辑分组,这个分组和bean自身的定义没有任何关系,无论是xml还是注解形式,都能够配置bean属于哪一个profile分组。

当存在多个profile分组时,咱们能够指定哪一个profile失效,当然如果不指定,spring会依据默认的profile去执行。咱们来通过一个代码演示一下。

ProfileService

创立一个一般的类,代码如下

public class ProfileService {    private String profile;    public ProfileService(String profile) {        this.profile = profile;    }    @Override    public String toString() {        return "ProfileService{" +                "profile='" + profile + '\'' +                '}';    }}

申明一个配置类

在配置类中,构建两个bean,配置不同的profile。

@Configurationpublic class ProfileConfiguration {    @Bean    @Profile("dev")    public ProfileService profileServiceDev(){        return new ProfileService("dev");    }    @Bean    @Profile("prod")    public ProfileService profileServiceProd(){        return new ProfileService("prod");    }}

定义测试方法

public class ProfileMain {    public static void main(String[] args) {        AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext();//        applicationContext.getEnvironment().setActiveProfiles("prod");        applicationContext.register(ProfileConfiguration.class);        applicationContext.refresh();        System.out.println(applicationContext.getBean(ProfileService.class));    }}

能够通过很多种形式来激活配置,默认状况下不增加applicationContext.getEnvironment().setActiveProfiles("prod");时,会发现bean没有被装载。增加了之后,会依据以后激活的profiles来决定装载哪个bean。

除此之外,咱们还能够在启动参数中减少-Dspring.profiles.active=prod来决定以后激活哪个profile。该属性能够配置在零碎环境变量、JVM零碎属性、等。

留神配置文件不是单选;可能会同时激活多个配置文件,编程式的应用办法setActiveProfiles(),该办法接管String数组参数,也就是多个配置文件名
applicationContext.getEnvironment().setActiveProfiles("prod","dev");

如果没有任何profile配置被激活,默认的profile将会激活。
默认profile配置文件能够更改,通过环境变量的setDefaultProfiles办法,或者是申明的spring.profiles.default属性值

profiles总结

简略总结一下profiles,通过profiles能够最一组bean进行逻辑分组,这些逻辑分组的bean会依据Environment上下文中配置的激活的profile来进行加载,也就是Environment对于profiles配置来说,它能决定以后激活的是哪个profile配置。

  • 一个profile就是一组Bean定义的逻辑分组。
  • 这个分组,也就 这个profile,被赋予一个命名,就是这个profile名字。
  • 只有当一个profile处于active状态时,它对应的逻辑上组织在一起的这些Bean定义才会被注册到容器中。
  • Bean增加到profile能够通过XML定义形式或者annotation注解形式。
  • Environment对于profile所表演的角色是用来指定哪些profile是以后沉闷的缺省。

Properties

properties的作用就是用来寄存属性的,它能够帮咱们治理各种配置信息。这个配置的起源能够是properties文件、JVM properties、零碎环境变量、或者专门的Properties对象等。

咱们来看一下Environment这个接口,它继承了PropertyResolver,这个接口和属性的操作无关,也就是咱们能够通过Environment来设置和取得相干属性。

public interface Environment extends PropertyResolver {    String[] getActiveProfiles();    String[] getDefaultProfiles();    /** @deprecated */    @Deprecated    boolean acceptsProfiles(String... var1);    boolean acceptsProfiles(Profiles var1);}

至此,咱们能够能够简略的总结Environment的作用,Environment提供了不同的profile配置,而PropertyResolver提供了配置的操作,由此咱们能够晓得,Spring 容器能够依据不同的profile来获取不同的配置信息,从而实现Spring容器中运行时环境的解决。

environment的利用

  • 在spring boot利用中,批改application.properties配置

    env=default
  • 创立一个Controller进行测试

    @RestControllerpublic class EnvironementController {    @Autowired    Environment environment;    @GetMapping("/env")    public String env(){        return environment.getProperty("env");    }}

指定profile属性

在后面的内容中咱们介绍了profile和property这两个概念,当初咱们来联合应用加深对这两者的了解。

在spring boot利用中,默认的内部化配置是application.properties文件,事实上,除了这个默认的配置文件之外,咱们还能够应用springboot中的约定命名格局来实现不同环境的配置

application-profile.properties

以后spring boot利用抉择应用哪个properties文件作为上下文环境配置,取决与以后激活的profile。同样,咱们能够通过很多种形式来激活,比方在application.properties中减少spring.profiles.active=dev这种形式,也能够在JVM参数中减少该配置来指定失效的配置。

在不指定的状况下,则应用默认的配置文件,简略来说,如果没有显式激活某一个配置文件,那么应用程序就将加载application-default.properties中的属性。

这个性能十分实用,个别的公司外面都会有几套运行环境,比方开发、测试、生产环境,这些环境中会有一些配置信息是不同的,比方服务器地址。那咱们须要针对不同的环境应用指定的配置信息,通过这种形式就能够很不便的去解决。

@Value注解的应用

在properties文件中定义的属性,除了能够通过environment的getProperty办法获取之外,spring还提供了@Value注解,

@RestControllerpublic class EnvironementController {    @Value("${env}")    private String env;    @GetMapping("/env")    public String env(){        return env;    }}

spring容器在加载一个bean时,当发现这个Bean中有@Value注解时,那么它能够从Environment中将属性值进行注入,如果Environment中没有这个属性,则会报错。

Spring Environment原理设计

联合后面咱们讲过的内容,咱们来揣测一下Environment的实现原理。

简略演示一下Environment中的配置起源
  • @Value("${java.version}") 获取System.getProperties , 获取零碎属性
  • 配置command的jvm参数, -Denvtest=command

基于现有的内容的推导,咱们能够画出上面这样一个图。

  • 第一局部是属性定义,这个属性定义能够来自于很多中央,比方application.properties、或者零碎环境变量等。
  • 而后依据约定的形式去指定门路或者指定范畴去加载这些配置,保留到内存中。
  • 最初,咱们能够依据指定的key从缓存中去查找这个值。

上面这个是示意Environment的类关系图,这个类关系图还是十分清晰的体现了Environment的原理。

上述类图的外围API阐明如下

  1. Environment接口,继承了PropertyResolver。 PropertyResolver,它次要有两个作用。

    • 通过propertyName属性名获取与之对应的propertValue属性值(getProperty)。
    • ${propertyName:defaultValue}格局的属性占位符,替换为理论的值(resolvePlaceholders)。
  2. PropertyResolver的具体实现类是PropertySourcesPropertyResolver,属性源的解决方案。该类是体系中惟一的残缺实现类。它以PropertySources属性源汇合(外部持有属性源列表List<PropertySource>)为属性值的起源,按序遍历每个PropertySource,获取到一个非null的属性值则返回。

其中,PropertySourcesPropertyResolver中的List<PropertySource>,示意不同属性源的起源,它的类关系图如下,示意针对不同数据源的存储。

版权申明:本博客所有文章除特地申明外,均采纳 CC BY-NC-SA 4.0 许可协定。转载请注明来自 Mic带你学架构
如果本篇文章对您有帮忙,还请帮忙点个关注和赞,您的保持是我一直创作的能源。欢送关注同名微信公众号获取更多技术干货!