Spring Boot自定义配置属性源(PropertySource)

配置覆盖优于profile

在生产实践中,配置覆盖是解决不同环境不同配置的常用方法。比如用生产服务器上的配置文件覆盖包内的文件,或者使用中心化的配置服务来覆盖默认的业务配置。

相比于profile机制(比如maven的profile、spring boot的profile-specific properties),即不同环境使用不同的配置文件,覆盖的方式更有优势。程序员在开发时不需要关心生产环境数据库的地址、账号等信息,一次构建即可在不同环境中运行,而profile机制需要将生产环境的配置写到项目资源文件中,而且要为不同环境使用不同的构建参数或者运行参数。

Spring提供了灵活的配置扩展能力,有多种方式将自定义的属性源,将集成进来,可以轻松地实现配置覆盖。

本文基于Spring Boot 1.4.8/Spring 4.3.12编写

使用@PropertySource注解实现自定义配置文件和配置覆盖

@ConfigurationProperties
@Configuration
public class DemoProperties {
  // properties with getter/setters
}
@PropertySource(value = {
    "test.properties",
    "file:/etc/test.properties",
},
    ignoreResourceNotFound = true)
@Configuration
public class DemoAutoConfiguration {

  @Autowired
  private DemoProperties demoProperties;

  @PostConstruct
  public void init() {
    System.out.println(demoProperties);
  }
}

Spring支持使用PropertySource注解引入自定义配置文件,其中"test.properties"将使Spring从classpath下加载该文件,"file:/etc/test.properties"将使Spring从文件系统加载/etc/test.properties文件,ignoreResourceNotFound = true使Spring忽略文件加载失败的异常,即配置文件是可选的。

同时,由于"file:/etc/test.properties"位于"test.properties"之后,这使得文件系统的配置文件可以覆盖classpath下的配置。

自定义属性源工厂

如果想要更加灵活的自定义属性源,比如实现从中心化的配置服务加载配置,可以通过实现PropertySourceFactory接口,并通过配置PropertySource注解的factory参数来实现。

@Configuration
@PropertySource(value = ""/*placeholder*/,
    factory = CompositePropertySourceFactory.class)
public class CompositeConfigAutoConfiguration {
}

value字段用于指定配置源对应的资源文件,如果不需要使用资源文件,可以配置为任意值,参数值将会被传递到factory参数的createPropertySource方法。

如果ignoreResourceNotFound字段指定为true,那么factory抛出的异常将被忽略,否则将导致启动失败。有的时候,直接把启动失败暴露出来不失为一种好的做法。

PropertySourceFactory接口的定义如下:

/**
 * Strategy interface for creating resource-based {@link PropertySource} wrappers.
 *
 * @author Juergen Hoeller
 * @since 4.3
 * @see DefaultPropertySourceFactory
 */
public interface PropertySourceFactory {

 /**
 * Create a {@link PropertySource} that wraps the given resource.
 * @param name the name of the property source
 * @param resource the resource (potentially encoded) to wrap
 * @return the new {@link PropertySource} (never {@code null})
 * @throws IOException if resource resolution failed
 */
 PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException;

}

需要注意的是PropertySourceFactory的加载时机早于Spring Beans容器,因此实现上不能依赖于Spring的IOC。

PropertySourceFactory要求实现类返回PropertySource。PropertySource是Spring属性(或者说配置)功能的核心接口,有很多实现,比如:

  1. ResourcePropertySource 从Resource加载PropertySource
  2. PropertiesPropertySource 从properties文件加载PropertySource
  3. SystemEnvironmentPropertySource 从系统环境变量加载PropertySource
  4. MapPropertySource 包装一个Map为PropertySource(Adapter模块)
  5. CompositePropertySource 支持将若干PropertySource进行组合(Composite模式)

实际实现类远不如这些,具体的可以阅读Spring文档或源码。

在自定义属性源时比较常用的是MapPropertySource和CompositePropertySource。

MapPropertySource可以用于将自己加载的属性数据包装,参考其构造方法。

public MapPropertySource(String name, Map<String, Object> source) {
 super(name, source);
}

后者可以通过组合装载多个属性源并自定义覆盖顺序。例如:

PropertySource<?> packageInsidePropertySource = packageInsidePropertySourceIterateLoader.loadPropertySource(compositePropertySource);
compositePropertySource.addPropertySource(packageInsidePropertySource);

PropertySource<?> outerFilePropertySource = outerFilePropertySourceIterateLoader.loadPropertySource(compositePropertySource);
// 优先级高于前者
compositePropertySource.addFirstPropertySource(outerFilePropertySource);

addFirstPropertySource方法可以设置传入的PropertySource为最高优先级(在此CompositePropertySource内部),addPropertySource方法则相反,放在后面的优先级更低。

加载依赖jar包中所有同名配置文件

直接从classpath加载配置文件,要求文件必须存在于classpath中。考虑在WEB项目中,如果文件存在于某个依赖的jar包中,即位于WEB-INF/lib/xxx.jar中,此时基于classpath无法直接加载。此时可以使用Spring提供的PathMatchingResourcePatternResolver,按资源名称扫描所有jar包来实现目的。

private List<Resource> getPackageInsideResourcesByPattern(String resourceName) throws IOException {
 String resourcePathPattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + HbootConfigConstants.CONFIGS + resourceName;
 ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
 return Arrays.asList(resourcePatternResolver.getResources(resourcePathPattern));
}

然后就可以使用ResourcePropertySource从Resource构建PropertySource传给Spring。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 详解Spring Boot 自定义PropertySourceLoader

    SpringBoot 的配置文件内置支持 properties.xml.yml.yaml 几种格式,其中 properties和xml 对应的Loader类为 PropertiesPropertySourceLoader ,yml和yaml 对应的Loader类为 YamlPropertySourceLoader. 观察这2个类可以发现,都实现自接口 PropertySourceLoader .所以我们要新增支持别的格式的配置文件,就可以通过实现接口 PropertySourceLoader 来

  • Spring boot中PropertySource注解的使用方法详解

    前言 本文将重点讲解一下Spring中@PropertySource注解的使用,如何通过PropertySource注解加载指定的配置文件.以及PropertySource注解与@ConfigurationProperties两个注解的配合使用.下面话不多说了,来随着小编来一起学习学习吧. 1.1. PropertySource注解加载指定的属性文件 Spring框架提供了PropertySource注解,目的是加载指定的属性文件,接下来我们看一下如何使用该注解.首先我们定义一个配置类,并在类中

  • Spring Boot自定义配置属性源(PropertySource)

    配置覆盖优于profile 在生产实践中,配置覆盖是解决不同环境不同配置的常用方法.比如用生产服务器上的配置文件覆盖包内的文件,或者使用中心化的配置服务来覆盖默认的业务配置. 相比于profile机制(比如maven的profile.spring boot的profile-specific properties),即不同环境使用不同的配置文件,覆盖的方式更有优势.程序员在开发时不需要关心生产环境数据库的地址.账号等信息,一次构建即可在不同环境中运行,而profile机制需要将生产环境的配置写到项

  • Spring Boot自定义配置实现IDE自动提示功能

    一.背景 官方提供的spring boot starter的配置项,我们用IDE配置的时候一般都有自动提示的,如下图所示 而我们自己自定义的配置却没有,对开发非常不友好容易打错配置, 那这个是怎样实现的呢? 二.提示原理 IDE是通过读取配置信息的元数据而实现自动提示的,而元数据在目录 META-INF 中的 spring-configuration-metadata.json 或者 additional-spring-configuration-metadata.json 三.实现自动提示 以

  • spring boot自定义配置源操作步骤

    概述 我们知道,在Spring boot中可以通过xml或者@ImportResource 来引入自己的配置文件,但是这里有个限制,必须是本地,而且格式只能是 properties(或者 yaml).那么,如果我们有远程配置,如何把他引入进来来呢. 如何做 其实自定义配置源只需要3步 第一步,编写PropertySource 编写一个类继承EnumerablePropertySource,然后实现它的抽象方法即可,抽象方法看名字就知道作用,简单起见,这里使用一个map来保存配置,例如: publ

  • Spring Boot读取配置属性常用方法解析

    1. 前言 在Spring Boot项目中我们经常需要读取application.yml配置文件的自定义配置,今天就来罗列一下从yaml读取配置文件的一些常用手段和方法. 2. @Value 首先,会想到使用@Value注解,该注解只能去解析yaml文件中的简单类型,并绑定到对象属性中去. felord: phone: 182******32 def: name: 码农小胖哥 blog: felord.cn we-chat: MSW_623 dev: name: 码农小胖哥 blog: felo

  • Spring boot将配置属性注入到bean类中

    一.@ConfigurationProperties注解的使用 看配置文件,我的是yaml格式的配置: // file application.yml my: servers: - dev.bar.com - foo.bar.com - jiaobuchong.com 下面我要将上面的配置属性注入到一个Java Bean类中,看码: import org.springframework.boot.context.properties.ConfigurationProperties; import

  • spring 和 spring boot 中的属性配置方式

    目录 在xml中注册属性文件 多个 通过java注解方式注册属性文件 使用及注入属性 属性搜索优先级 spring boot 属性加载 application.properties – 缺省属性文件 特定环境属性文件 特定测试属性文件 @TestPropertySource注解 层次属性 YAML 文件 命令行传入属性 环境变量属性 随机属性值 其他类型的属性源 spring配置实现 多层级上下文中属性加载 属性文件通过定义xml中 属性文件通过@PropertySource定义在java中 总

  • spring boot 自定义starter的实现教程

    spring boot 使用 starter 解决了很多配置问题, 但是, 他是怎么来解决这些问题的呢? 这里通过一个简单的例子, 来看一下, starter是怎么来设置默认配置的. 一. 建 starter 项目 自定义的starter, 项目命名规范是: 自定义名-spring-boot-starter 先来看一下, 我最后的目录结构 1. 修改pom.xml文件 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns

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

    前言 在项目中为了灵活配置,我们常采用配置文件,常见的配置文件就比如xml和properties,springboot允许使用properties和yaml文件作为外部配置.现在编译器对于yaml语言的支持还不够好,目前还是使用properties文件作为外部配置. 在Spring cloud config出来之前, 自己实现了基于ZK的配置中心, 杜绝了本地properties配置文件, 原理很简单, 只是重载了PropertyPlaceholderConfigurer的mergeProper

  • Spring Boot Security配置教程

    1.简介 在本文中,我们将了解Spring Boot对spring Security的支持. 简而言之,我们将专注于默认Security配置以及如何在需要时禁用或自定义它. 2.默认Security设置 为了增加Spring Boot应用程序的安全性,我们需要添加安全启动器依赖项: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-

  • spring boot自定义log4j2日志文件的实例讲解

    背景:因为从 spring boot 1.4开始的版本就要用log4j2 了,支持的格式有json和xml两种格式,此次实践主要使用的是xml的格式定义日志说明. spring boot 1.5.8.RELEASE 引入log4j2的开发步骤如下: 1.首先把spring-boot-starter-web以及spring-boot-starter包下面的spring-boot-starter-logging排除,然后引入spring-boot-starter-log4j2包. <dependen

随机推荐