前言
项目开发中经常需要加载外部资源文件,@PropertySource
给我们提供了极大的便利。但是@PropertySource
目前不支持 yml 文件的解析,由于 yml 结构清晰等优点,使用频率也会越来越高。
源码解读
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {
/**
* Indicate the name of this property source. If omitted, a name will
* be generated based on the description of the underlying resource.
* @see org.springframework.core.env.PropertySource#getName()
* @see org.springframework.core.io.Resource#getDescription()
*/
String name() default "";
/**
* Indicate the resource location(s) of the properties file to be loaded.
* <p>Both traditional and XML-based properties file formats are supported
* — for example, {@code "classpath:/com/myco/app.properties"}
* or {@code "file:/path/to/file.xml"}.
* <p>Resource location wildcards (e.g. **/*.properties) are not permitted;
* each location must evaluate to exactly one {@code .properties} resource.
* <p>${...} placeholders will be resolved against any/all property sources already
* registered with the {@code Environment}. See {@linkplain PropertySource above}
* for examples.
* <p>Each location will be added to the enclosing {@code Environment} as its own
* property source, and in the order declared.
*/
String[] value();
/**
* Indicate if failure to find the a {@link #value() property resource} should be
* ignored.
* <p>{@code true} is appropriate if the properties file is completely optional.
* Default is {@code false}.
* @since 4.0
*/
boolean ignoreResourceNotFound() default false;
/**
* A specific character encoding for the given resources, e.g. "UTF-8".
* @since 4.3
*/
String encoding() default "";
/**
* Specify a custom {@link PropertySourceFactory}, if any.
* <p>By default, a default factory for standard resource files will be used.
* @since 4.3
* @see org.springframework.core.io.support.DefaultPropertySourceFactory
* @see org.springframework.core.io.support.ResourcePropertySource
*/
Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}
注意 factory 这个属性,作为解析资源文件的工厂类,默认实现是 DefaultPropertySourceFactory
:
public class DefaultPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException {
return (name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource));
}
}
编码实现
我们只需要自定义一个工厂类 ResourceFactory
,继承这个 default 工厂,重写 createPropertySource
即可:
public class ResourceFactory extends DefaultPropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
String sourceName = (name == null) ? resource.getResource().getFilename() : name;
assert sourceName != null;
if (sourceName.endsWith(".yml") || sourceName.endsWith(".yaml")) {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
Properties properties = factory.getObject();
assert properties != null;
return new PropertiesPropertySource(sourceName, properties);
}
return super.createPropertySource(name, resource);
}
}
新建测试文件 sso.yml:
sso:
url: "http://www.baidu.com"
name: sso-service
结合 @ConfigurationProperties
实现 sso 配置类注入:
@Data
@Component
@ConfigurationProperties("sso")
@PropertySource(value = "classpath:sso.yml", factory = ResourceFactory.class)
public class Sso {
private String url;
private String name;
@PostConstruct
public void test(){
System.out.println(this);
}
}
test
方法作为测试输出当前信息:
Sso(url=http://www.baidu.com, name=sso-service)
网友评论