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

 更新时间:2018年06月13日 14:46:47   作者:曹书豪  
这篇文章主要介绍了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。

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

相关文章

  • DoytoQuery中的关联查询方案示例详解

    DoytoQuery中的关联查询方案示例详解

    这篇文章主要为大家介绍了DoytoQuery中的关联查询方案示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • 老生常谈Java网络编程TCP通信(必看篇)

    老生常谈Java网络编程TCP通信(必看篇)

    下面小编就为大家带来一篇老生常谈Java网络编程TCP通信(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • java中单双斜杠的使用图文详解

    java中单双斜杠的使用图文详解

    JAVA中的斜杠有正斜杠与反斜杠之分,正斜杠,一般就叫做斜杠,下面这篇文章主要给大家介绍了关于java中单双斜杠使用的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • SpringBoot集成swagger的实例代码

    SpringBoot集成swagger的实例代码

    Swagger 是一款RESTFUL接口的文档在线自动生成+功能测试功能软件,这篇文章主要介绍了SpringBoot集成swagger,需要的朋友可以参考下
    2017-12-12
  • SpringBoot整合JWT实战教程

    SpringBoot整合JWT实战教程

    JWT(JSON Web Token)是一种用于身份验证和授权的开放标准(RFC 7519),它使用JSON格式传输信息,可以在不同系统之间安全地传递数据,这篇文章主要介绍了SpringBoot整合JWT实战教程,需要的朋友可以参考下
    2023-06-06
  • SpringBoot配置默认HikariCP数据源

    SpringBoot配置默认HikariCP数据源

    咱们开发项目的过程中用到很多的开源数据库链接池,比如druid、c3p0、BoneCP等等,本文主要介绍了SpringBoot配置默认HikariCP数据源,具有一定的参考价值,感兴趣的可以了解一下
    2023-11-11
  • java中Map接口常用的方法解读

    java中Map接口常用的方法解读

    这篇文章主要介绍了java中Map接口常用的方法解读,Map接口是双列集合,它的每一个元素都包含一个键对象key和值对象Value,键和值对象之间存在一种对应关系,称为映射,需要的朋友可以参考下
    2024-01-01
  • 详解MyBatis Plus中分页插件的使用

    详解MyBatis Plus中分页插件的使用

    这篇文章主要为大家详细介绍了MyBatis Plus中分页插件使用的相关知识,文中的示例代码讲解详细,具有一定的学习价值,感兴趣的小伙伴可以了解一下
    2023-02-02
  • javaWeb用户权限控制简单实现过程

    javaWeb用户权限控制简单实现过程

    这篇文章主要为大家详细介绍了javaWeb用户权限控制简单实现过程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • 一文带你全面了解Java Hashtable

    一文带你全面了解Java Hashtable

    HashTable是jdk 1.0中引入的产物,基本上现在很少使用了,但是会在面试中经常被问到。本文就来带大家一起深入了解一下Hashtable,需要的可以参考一下
    2022-09-09

最新评论