Spring boot外部配置(配置中心化)详解

作者:BlogJava-专家区 时间:2022-07-11 23:13:26 

前言

在项目中为了灵活配置,我们常采用配置文件,常见的配置文件就比如xml和properties,springboot允许使用properties和yaml文件作为外部配置。现在编译器对于yaml语言的支持还不够好,目前还是使用properties文件作为外部配置。

在Spring cloud config出来之前, 自己实现了基于ZK的配置中心, 杜绝了本地properties配置文件, 原理很简单, 只是重载了PropertyPlaceholderConfigurer的mergeProperties() :


/**
* 重载合并属性实现
* 先加载file properties, 然后并入ZK配置中心读取的properties
*
* @return 合并后的属性集合
* @throws IOException 异常
*/
@Override
protected Properties mergeProperties() throws IOException {
Properties result = new Properties();
// 加载父类的配置
Properties mergeProperties = super.mergeProperties();
result.putAll(mergeProperties);
// 加载从zk中读取到的配置
Map<String, String> configs = loadZkConfigs();
result.putAll(configs);
return result;
}

这个实现在spring项目里用起来还是挺顺手的, 但是近期部分spring-boot项目里发现这种placeholder的实现跟spring boot的@ConfigurationProperties(prefix = "xxx") 不能很好的配合工作,

也就是属性没有被resolve处理, 用@Value的方式确可以读到, 但是@Value配置起来如果属性多的话还是挺繁琐的, 还是倾向用@ConfigurationProperties的prefix, 于是看了下spring boot的文档发现 PropertySource

order:

* Devtools global settings properties on your home directory (~/.spring-boot-devtools.properties when devtools is active).

* @TestPropertySource annotations on your tests.

* @SpringBootTest#properties annotation attribute on your tests.

* Command line arguments.

* Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property)

* ServletConfig init parameters.

* ServletContext init parameters.

* JNDI attributes from java:comp/env.

* Java System properties (System.getProperties()).

* OS environment variables.

* A RandomValuePropertySource that only has properties in random.*.

* Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants)

* Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants)

* Application properties outside of your packaged jar (application.properties and YAML variants).

* Application properties packaged inside your jar (application.properties and YAML variants).

* @PropertySource annotations on your @Configuration classes.

* Default properties (specified using SpringApplication.setDefaultProperties).

不难发现其会检查Java system propeties里的属性, 也就是说, 只要把mergerProperties读到的属性写入Java system props里即可, 看了下源码, 找到个切入点


/**
* 重载处理属性实现
* 根据选项, 决定是否将合并后的props写入系统属性, Spring boot需要
*
* @param beanFactoryToProcess
* @param props    合并后的属性
* @throws BeansException
*/
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
// 原有逻辑
 super.processProperties(beanFactoryToProcess, props);
// 写入到系统属性
if (writePropsToSystem) {
 // write all properties to system for spring boot
 Enumeration<?> propertyNames = props.propertyNames();
 while (propertyNames.hasMoreElements()) {
   String propertyName = (String) propertyNames.nextElement();
   String propertyValue = props.getProperty(propertyName);
   System.setProperty(propertyName, propertyValue);
 }
}
}

为避免影响过大, 设置了个开关, 是否写入系统属性, 如果是spring boot的项目, 就开启, 这样对线上非spring boot项目做到影响最小, 然后spring boot的@ConfigurationProperties完美读到属性;

具体代码见: org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor


@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
 throws BeansException {
ConfigurationProperties annotation = AnnotationUtils
  .findAnnotation(bean.getClass(), ConfigurationProperties.class);
if (annotation != null) {
 postProcessBeforeInitialization(bean, beanName, annotation);
}
annotation = this.beans.findFactoryAnnotation(beanName,
ConfigurationProperties.class);
if (annotation != null) {
 postProcessBeforeInitialization(bean, beanName, annotation);
}
return bean;
}

来源:http://www.blogjava.net/miaoyachun/archive/2017/12/08/432940.html

标签:springboot,外部配置,配置中心化
0
投稿

猜你喜欢

  • android获取ibeacon列表的方法

    2023-01-18 00:57:54
  • java操作solr实现查询功能的实例

    2023-08-04 10:41:34
  • 21天学习android开发教程之SurfaceView与多线程的混搭

    2021-07-22 05:25:09
  • Android中Retrofit 2.0直接使用JSON进行数据交互

    2022-01-08 07:22:46
  • C语言malloc分配问题详解

    2023-07-22 05:10:34
  • Java Stax解析XML示例

    2022-04-07 13:42:15
  • Java常用工具类—集合排序

    2022-07-08 08:05:39
  • 详解Android版本适配:9.0 Pie

    2022-08-07 05:37:43
  • Maven的安装配置详解

    2023-11-24 08:52:05
  • Java Web实现简易图书管理系统

    2023-12-17 21:48:34
  • Java语言求解完美数代码分析

    2023-01-28 10:17:58
  • 浅谈JVM垃圾回收之哪些对象可以被回收

    2021-08-14 18:57:47
  • Android 添加TextView删除线(代码简单)

    2022-05-27 16:48:47
  • GC调优实战之过早提升Premature Promotion

    2023-10-22 10:07:55
  • 详解Springboot对多线程的支持

    2023-09-21 02:18:21
  • Android自定义view实现滚动选择控件详解

    2022-12-05 09:54:06
  • 基于jdk1.8的Java源码详解 Integer

    2023-05-08 11:32:22
  • C#利用Task实现任务超时多任务一起执行的方法

    2023-07-04 20:03:38
  • Android 按指定大小读取图片的实例

    2022-06-16 18:26:25
  • Android7.0开发实现Launcher3去掉应用抽屉的方法详解

    2021-07-24 12:31:38
  • asp之家 软件编程 m.aspxhome.com