Spring中的Environment外部化配置管理详解
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说明如下
Environment接口,继承了PropertyResolver。 PropertyResolver,它主要有两个作用。
通过
propertyName
属性名获取与之对应的propertValue
属性值(getProperty)。把
${propertyName:defaultValue}
格式的属性占位符,替换为实际的值(resolvePlaceholders)。
PropertyResolver的具体实现类是PropertySourcesPropertyResolver,属性源的解决方案。该类是体系中唯一的完整实现类。它以PropertySources属性源集合(内部持有属性源列表List)为属性值的来源,按序遍历每个PropertySource,获取到一个非null的属性值则返回。
其中,PropertySourcesPropertyResolver中的List,表示不同属性源的来源,它的类关系图如下,表示针对不同数据源的存储。
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
Mic带你学架构
!
如果本篇文章对您有帮助,还请帮忙点个关注和赞,您的坚持是我不断创作的动力。欢迎关注「跟着Mic学架构」公众号公众号获取更多技术干货!
Spring中的Environment外部化配置管理详解的更多相关文章
- Spring中@Component注解,@Controller注解详解
在使用Spring的过程中,为了避免大量使用Bean注入的Xml配置文件,我们会采用Spring提供的自动扫描注入的方式,只需要添加几行自动注入的的配置,便可以完成 Service层,Controll ...
- spring中bean标签factory-method和factory-bean)详解工厂方法(factory-method和factory-bean)
转自:http://blog.sina.com.cn/s/blog_6d3c1ec601019f3j.html A.factory-method The name of a factory metho ...
- Spring Boot 启动(二) 配置详解
Spring Boot 启动(二) 配置详解 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10198698.html) Spring Boot 配置 ...
- 【转】angularjs指令中的compile与link函数详解
这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下 通常大家在 ...
- angularjs指令中的compile与link函数详解
这篇文章主要介绍了angularjs指令中的compile与link函数详解,本文同时诉大家complie,pre-link,post-link的用法与区别等内容,需要的朋友可以参考下 通常大家在 ...
- (转)java之Spring(IOC)注解装配Bean详解
java之Spring(IOC)注解装配Bean详解 在这里我们要详细说明一下利用Annotation-注解来装配Bean. 因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看 ...
- 转载 Spring、Spring MVC、MyBatis整合文件配置详解
Spring.Spring MVC.MyBatis整合文件配置详解 使用SSM框架做了几个小项目了,感觉还不错是时候总结一下了.先总结一下SSM整合的文件配置.其实具体的用法最好还是看官方文档. ...
- saltstack自动化运维系列⑤之saltstack的配置管理详解
saltstack自动化运维系列⑤之saltstack的配置管理详解 配置管理初始化: a.服务端配置vim /etc/salt/master file_roots: base: - /srv/sal ...
- Quartz学习——SSMM(Spring+SpringMVC+Mybatis+Mysql)和Quartz集成详解(转)
通过前面的学习,你可能大致了解了Quartz,本篇博文为你打开学习SSMM+Quartz的旅程!欢迎上车,开始美好的旅程! 本篇是在SSM框架基础上进行的. 参考文章: 1.Quartz学习——Qua ...
随机推荐
- 微信小程序base64图片保存到手机相册
问题:base64图片不能直接用wx.saveImageToPhotosAlbum保存到手机相册 解决: 先用fs.writeFile写入本地文件,再wx.saveImageToPhotosAlbum ...
- 使用结构化克隆在 JavaScript 中进行深度复制
在很长一段时间内,您不得不求助于变通方法和库来创建 JavaScript 值的深层副本.现在js提供 「structuredClone()」 一个用于深度复制的内置函数. 浏览器支持: 浅拷贝 在 J ...
- Nginx高级模块学习
Nginx的rewrite规则 实现url重写一级重定向 使用场景: 1.URL访问跳转,支持开发设计 页面跳转.兼容性支持.展示效果 2.SEO优化 3.维护 后台维护.流量转发等 4.安全 配置语 ...
- WebRTC本地选择codec(web本地模拟)
视频编码后,再进行发送.WebRTC建立视频连接前,可以选择codec.一般来说支持多种codec,以VP8和H264为代表. Codec: 编码译码器,编解码器 示例代码 写一个示例,用户可以在发送 ...
- C\C++ IDE 比较以及调试
C\C++ IDE 比较以及调试 内容概要 这个作业属于哪个课程 2022面向对象程序设计 这个作业要求在哪里 2022面向对象程序设计寒假作业1 这个作业的目标 IDE 选择以及代码调试 作业正文 ...
- 安装MySQL到Ubuntu 20.04
本文的内容主要来自对How To Install MySQL on Ubuntu 20.04的翻译.在根据该文的指导下,我在自己的Ubuntu 20.04.3 LTS版本中安装了MySQL 8. St ...
- Golang 通过创建临时结构体实现 struct 内 interface struct 的 json 反序列化
原文链接 背景 type AData struct { A string `json:"a"` } type BData struct { B string `json:" ...
- 随机IP代理插件Scrapy-Proxies
安装: pip install scrapy_proxies github: https://github.com/aivarsk/scrapy-proxies scrapy爬虫配置文件setti ...
- django之django-debug-toolbar调试工具配置与使用
外部链接:https://blog.csdn.net/weixin_39198406/article/details/78821677 django-debug-toolbar的作用:进行性能调优,与 ...
- PostgreSQL逻辑订阅
测试环境:PostgreSQL 13.2 1.逻辑订阅简介 由于物理复制只能做到这个集群的复制,不能正对某个对象(表)进行复制,且物理复制的备库只能读,不能写.相反,逻辑订阅同时支持主备库读写,且可以 ...