@PropertySource 解析 yml 配置文件,自定义解析 yaml 工厂类
程序员文章站
2022-05-02 12:27:12
...
自定义解析 yaml 工厂类,YamlPropertySourceFactory
参考代码,见 github:
https://github.com/tudan110/learn-dev-tools
@PropertySource 注解
使用 @PropertySource 注解,可以编写配置文件的映射类,取代 @Value,在需要用到的地方,用 @Autowire 自动装配配置类即可。
源码如下
public @interface PropertySource {
/** 加载资源的名称 */
String name () default "";
/**
* 加载资源的路径,可使用 classpath, 如:
* "classpath:/config/test.yml"
* 如有多个文件路径放在 {} 中,使用 ',' 号隔开,如:
* {"classpath:/config/test1.yml","classpath:/config/test2.yml"}
* 除使用 classpath 外,还可使用文件的地址,如:
* "file:/rest/application.properties"
*/
String [] value ();
/** 此属性为根据资源路径找不到文件后是否报错,默认为是 false */
boolean ignoreResourceNotFound () default false;
/** 此为读取文件的编码,若配置中有中文建议使用 'utf-8' */
String encoding () default "";
/**
* 关键:此为读取资源文件的工程类,默认为:
* 'PropertySourceFactory.class'
*/
Class<? extends PropertySourceFactory> factory () default PropertySourceFactory.class;
}
其中 factory () 指定了解析配置文件的工厂类
使用参考示例,如下
@PropertySource (
name = "test.properties",
value = {"classpath:config/test.properties"},
ignoreResourceNotFound = false,
encoding = "UTF-8",
factory = DefaultPropertySourceFactory.class
)
PropertySourceFactory 接口
默认使用 @PropertySource 可以指定解析 properties 和 xml 配置文件,却不可以解析 yaml 配置文件,因为 spring 默认只有一个解析 properties 和 xml 文件的工厂类 DefaultPropertySourceFactory,没有解析 yaml 的工厂类,但是我们可以通过实现 PropertySourceFactory 接口自己写。
1. PropertySourceFactory 接口源码
发现其中只有一个方法 createPropertySource (),参考 DefaultPropertySourceFactory 类编写 yaml 解析工厂类。
package org.springframework.core.io.support;
import java.io.IOException;
import org.springframework.core.env.PropertySource;
import org.springframework.lang.Nullable;
public interface PropertySourceFactory {
PropertySource<?> createPropertySource (@Nullable String var1, EncodedResource var2) throws IOException;
}
2. DefaultPropertySourceFactory 源码
package org.springframework.core.io.support;
import java.io.IOException;
import org.springframework.core.env.PropertySource;
import org.springframework.lang.Nullable;
public class DefaultPropertySourceFactory implements PropertySourceFactory {
public DefaultPropertySourceFactory () {
}
public PropertySource<?> createPropertySource (@Nullable String name, EncodedResource resource) throws IOException {
return name != null ? new ResourcePropertySource (name, resource) : new ResourcePropertySource (resource);
}
}
3. 编写 yaml 解析工厂类
3.1 Maven 引入 yaml 工具包
spring 解析 yaml 依赖此包,不引入,用 maven-jar-plugin 打 jar 包后会出错
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${snakeyaml.version}</version>
</dependency>
3.2 自定义工厂类 YamlPropertySourceFactory
package indi.tudan.devtools.spring.core.io.support;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;
import org.springframework.lang.Nullable;
import java.io.IOException;
/**
* Yaml 配置文件读取工厂类
*
* @author wangtan
* @date 2019-11-29 14:37:44
* @since 1.0
*/
public class YamlPropertySourceFactory implements PropertySourceFactory {
public YamlPropertySourceFactory () {
}
/**
* yaml 文档解析方法
*
* @param name 配置项名称
* @param resource 配置项资源
* @return PropertySource<?>
* @throws IOException IOException
* @date 2019-11-29 14:45:00
* @since 1.0
*/
@Override
public PropertySource<?> createPropertySource (@Nullable String name, EncodedResource resource) throws IOException {
// 返回 yaml 属性资源
return new YamlPropertySourceLoader ()
.load (resource.getResource ().getFilename (), resource.getResource ())
.get (0);
}
}
yaml 配置文件
yaml:
name: wangtan
age: 26
# 可以用 数组 或 List 接收
pc: lenovo,dell
# 可以用 数组 或 List 接收
hobby:
- lol
- coding
编写配置映射类
在配置类中,指定解析 yaml 的自定义工厂类,factory = YamlPropertySourceFactory.class
package indi.tudan.devtools.common;
import indi.tudan.devtools.spring.core.io.support.YamlPropertySourceFactory;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* yaml 配置映射类
*
* @author wangtan
* @date 2019-11-28 17:26:39
* @since 1.0
*/
@Data
@Component
@PropertySource (
name = "test.yml",
value = {"classpath:config/test.yml"},
ignoreResourceNotFound = false,
encoding = "UTF-8",
factory = YamlPropertySourceFactory.class
)
@ConfigurationProperties (prefix = "yaml")
public class TestYaml {
private String name;
private int age;
private String [] pc;
//private List<String> pc;
private List<String> hobby;
//private String [] hobby;
}
使用配置类
package indi.tudan.devtools.processor;
import indi.tudan.devtools.common.TestYaml;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* yaml 配置处理器
*
* @author wangtan
* @date 2019-11-28 17:26:58
* @since 1.0
*/
@Component
@EnableConfigurationProperties
public class YamlProcessor {
@Autowired
private TestYaml testYaml;
/**
* 执行
*
* @date 2019-11-28 17:28:05
*/
public void start () {
System.out.println (testYaml.toString ());
}
}
控制台打印结果
TestYaml (name=wangtan, age=26, pc=[lenovo, dell], hobby=[lol, coding])