SpringBoot⾃定义配置属性源(PropertySource)
配置覆盖优于profile
在⽣产实践中,配置覆盖是解决不同环境不同配置的常⽤⽅法。⽐如⽤⽣产服务器上的配置⽂件覆盖包内的⽂件,或者使⽤中⼼化的配置服务来覆盖默认的业务配置。
相⽐于profile机制(⽐如maven的profile、spring boot的profile-specific properties),即不同环境使⽤不同的配置⽂件,覆盖的⽅式更有优势。程序员在开发时不需要关⼼⽣产环境数据库的地址、账号等信息,⼀次构建即可在不同环境中运⾏,⽽profile机制需要将⽣产环境的配置写到项⽬资源⽂件中,⽽且要为不同环境使⽤不同的构建参数或者运⾏参数。
Spring提供了灵活的配置扩展能⼒,有多种⽅式将⾃定义的属性源,将集成进来,可以轻松地实现配置覆盖。
本⽂基于Spring Boot 1.4.8/Spring 4.3.12编写
使⽤注解实现⾃定义配置⽂件和配置覆盖
@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
spring ioc注解@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提供的,按资源名称扫描所有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.Resources(resourcePathPattern));
}
然后就可以使⽤ResourcePropertySource从Resource构建PropertySource传给Spring。
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。