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

前言

在项目中为了灵活配置,我们常采用配置文件,常见的配置文件就比如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;
}

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • spring boot 日志配置详解

    最近在学习spring boot框架的路上,今日看了一下spring boot日志配置,顺便留个笔记记录一下. 1.新建logback.xml文件 内容如下: <!-- Logback configuration. See http://logback.qos.ch/manual/index.html --> <configuration scan="true" scanPeriod="10 seconds"> <include res

  • 基于spring boot 的配置参考大全(推荐)

    如下所示: # =================================================================== # COMMON SPRING BOOT PROPERTIES # # This sample file is provided as a guideline. Do NOT copy it in its # entirety to your own application. ^^^ # =============================

  • 详解Spring Boot 属性配置和使用

    spring Boot 允许通过外部配置让你在不同的环境使用同一应用程序的代码,简单说就是可以通过配置文件来注入属性或者修改默认的配置. Spring Boot 支持多种外部配置方式 这些方式优先级如下: 命令行参数 来自java:comp/env的JNDI属性 Java系统属性(System.getProperties()) 操作系统环境变量 RandomValuePropertySource配置的random.*属性值 jar包外部的application-{profile}.propert

  • Spring Boot 日志配置方法(超详细)

    默认日志 Logback : 默认情况下,Spring Boot会用Logback来记录日志,并用INFO级别输出到控制台.在运行应用程序和其他例子时,你应该已经看到很多INFO级别的日志了. 从上图可以看到,日志输出内容元素具体如下: 时间日期:精确到毫秒 日志级别:ERROR, WARN, INFO, DEBUG or TRACE 进程ID 分隔符:- 标识实际日志的开始 线程名:方括号括起来(可能会截断控制台输出) Logger名:通常使用源代码的类名 日志内容 添加日志依赖 假如mave

  • spring boot日志管理配置

    spring Boot在所有内部日志中使用Commons Logging,但是默认配置也提供了对常用日志的支持,如:Java Util Logging,Log4J,Log4J2和Logback.每种Logger都可以通过配置使用控制台或者文件输出日志内容. 控制台输出 在Spring Boot中默认配置了ERROR.WARN和INFO级别的日志输出到控制台. 我们可以通过两种方式切换至DEBUG级别: a.在运行命令后加入--debug标志,如:$ Java -jar myapp.jar --d

  • 详解spring boot 使用application.properties 进行外部配置

    application.properties大家都不陌生,我们在开发的时候,经常使用它来配置一些可以手动修改而且不用编译的变量,这样的作用在于,打成war包或者jar用于生产环境时,我们可以手动修改环境变量而不用再重新编译. spring boo默认已经配置了很多环境变量,例如,tomcat的默认端口是8080,项目的contextpath是"/"等等,可以在这里看spring boot默认的配置信息http://docs.spring.io/spring-boot/docs/curr

  • 详解Springboot配置文件的使用

    如果使用IDEA创建Springboot项目,默认会在resource目录下创建application.properties文件,在springboot项目中,也可以使用yml类型的配置文件代替properties文件 一.单个的获取配置文件中的内容 在字段上使用@Value("${配置文件中的key}")的方式获取单个的内容 1.在resource目录下创建application.yml文件,并添加一些配置,在yml文件中,key:后面需要添加一个空格,然后是value值,假设配置如

  • 深入理解Spring Boot属性配置文件

    前言 相信很多人选择Spring Boot主要是考虑到它既能兼顾Spring的强大功能,还能实现快速开发的便捷.我们在Spring Boot使用过程中,最直观的感受就是没有了原来自己整合Spring应用时繁多的XML配置内容,替代它的是在pom.xml中引入模块化的Starter POMs,其中各个模块都有自己的默认配置,所以如果不是特殊应用场景,就只需要在application.properties中完成一些属性配置就能开启各模块的应用. 在之前的各篇文章中都有提及关于application.

  • Spring Boot自定义错误视图的方法详解

    Spring Boot缺省错误视图解析器 Web应用在处理请求的过程中发生错误是非常常见的情况,SpringBoot中为我们实现了一个错误视图解析器(DefaultErrorViewResolver).它基于一些常见的约定,尝试根据HTTP错误状态码解析出错误处理视图.它会在目录/error下针对提供的HTTP错误状态码搜索模板或者静态资源,比如,给定了HTTP状态码404,它会尝试搜索如下模板或者静态资源: /<templates>/error/404.<ext> - 这里<

  • Spring Boot thymeleaf模板引擎的使用详解

    在早期开发的时候,我们完成的都是静态页面也就是html页面,随着时间轴的发展,慢慢的引入了jsp页面,当在后端服务查询到数据之后可以转发到jsp页面,可以轻松的使用jsp页面来实现数据的显示及交互,jsp有非常强大的功能,但是,在使用springboot的时候,整个项目是以jar包的方式运行而不是war包,而且还嵌入了tomcat容器,因此,在默认情况下是不支持jsp页面的.如果直接以纯静态页面的方式会给我们的开发带来很大的麻烦,springboot推荐使用模板引擎. 模板引擎有很多种,jsp,

  • spring boot微服务自定义starter原理详解

    这篇文章主要介绍了spring boot微服务自定义starter原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 使用spring boot开发微服务后,工程的数量大大增加(一定要按照领域来切,不要一个中间件客户端包一个),让各个jar从开发和运行时自包含成了一个重要的内容之一.spring boot starter就可以用来解决该问题(没事启动时别依赖于applicationContext.getBean获取bean进行处理,依赖关系

  • Spring boot注解@Async线程池实例详解

    这篇文章主要介绍了Spring boot注解@Async线程池实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 从Spring3开始提供了@Async注解,该注解可以被标注在方法上,以便异步地调用该方法.调用者将在调用时立即返回,方法的实际执行将提交给Spring TaskExecutor的任务中,由指定的线程池中的线程执行. 1. TaskExecutor Spring异步线程池的接口类,其实质是java.util.concurrent

  • Spring Boot 控制层之参数传递方法详解

    当然,您自己创建一个项目也是可以的. bean包下的Student.java package com.example.demo.bean; public class Student { private Integer id; //学号 private String name; //姓名 public Student() { } public Student(Integer id, String name) { this.id = id; this.name = name; } public In

  • spring boot Slf4j日志框架的体系结构详解

    目录 前言 一.五花八门的日志工具包 1.1. 日志框架 1.2.日志门面 1.3日志门面存在的意义 二.日志框架选型 三.日志级别 四.常见术语概念解析 总结 前言 刚刚接触到java log日志的同学可能会被各种日志框架吓到,包括各种日志框架之间的jar总是发生冲突,另很多小伙伴头疼不已.那我们本篇的内容就是将各种java 日志框架发展过程,以及他们之间的关系,以及如何选型来介绍给大家. 一.五花八门的日志工具包 1.1. 日志框架 JDK java.util.logging 包:java.

  • Spring Boot读取resources目录文件方法详解

    这篇文章主要介绍了Spring Boot读取resources目录文件方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在Java编码过程中,我们常常希望读取项目内的配置文件,按照Maven的习惯,这些文件一般放在项目的src/main/resources下,因此,合同协议PDF模板.Excel格式的统计报表等模板的存放位置是resources/template/test.pdf,下面提供两种读取方式,它们分别在windows和Linux

  • Spring Boot实现数据访问计数器方案详解

    目录 1.数据访问计数器 2.代码实现 2.1.方案说明 2.2.代码 2.3.调用 1.数据访问计数器   在Spring Boot项目中,有时需要数据访问计数器.大致有下列三种情形: 1)纯计数:如登录的密码错误计数,超过门限N次,则表示计数器满,此时可进行下一步处理,如锁定该账户. 2)时间滑动窗口:设窗口宽度为T,如果窗口中尾帧时间与首帧时间差大于T,则表示计数器满.   例如使用redis缓存时,使用key查询redis中数据,如果有此key数据,则返回对象数据:如无此key数据,则查

  • Spring Boot企业常用的starter示例详解

    SpringBoot简介# Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者. Spring Boot让我们的Spring应用变的更轻量化.比如:你可以仅仅依靠一个Java类来运行一个Spring引用.你也可以打包你的应用为

  • Spring Boot Async异步执行任务过程详解

    异步调用就是不用等待结果的返回就执行后面的逻辑,同步调用则需要等带结果再执行后面的逻辑. 通常我们使用异步操作都会去创建一个线程执行一段逻辑,然后把这个线程丢到线程池中去执行,代码如下: ExecutorService executorService = Executors.newFixedThreadPool(10); executorService.execute(() -> { try { // 业务逻辑 } catch (Exception e) { e.printStackTrace(

随机推荐