关于java:Spring中的Environment外部化配置管理详解

54次阅读

共计 4744 个字符,预计需要花费 12 分钟才能阅读完成。

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。

@Configuration
public 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 进行测试

    @RestController
    public 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 注解,

@RestController
public 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 带你学架构
如果本篇文章对您有帮忙,还请帮忙点个关注和赞,您的保持是我一直创作的能源。欢送关注同名微信公众号获取更多技术干货!

正文完
 0