org.springframework.beans.factory.config.YamlPropertiesFactoryBean 类详解
YamlPropertiesFactoryBean 类详解
1. 类继承结构关系
java.lang.Object↳ org.springframework.beans.factory.FactoryBean<java.util.Properties>↳ org.springframework.beans.factory.config.PropertiesFactoryBean↳ org.springframework.beans.factory.config.YamlPropertiesFactoryBean
FactoryBean<Properties>
:定义生成Properties
对象的接口,提供getObject()
方法返回目标对象。PropertiesFactoryBean
:父类,负责将资源(如文件、URL)转换为Properties
对象。YamlPropertiesFactoryBean
:子类,专门处理 YAML 格式的资源,依赖 SnakeYAML 库实现解析。
2. 类中所有方法详解
方法 | 说明 |
---|---|
setResources(Resource... resources) | 设置需要加载的资源(如文件路径、URL),支持多个资源合并。 |
setSingleton(boolean singleton) | 是否将生成的 Properties 对象标记为单例(默认 true )。 |
getObject() | 核心方法,返回转换后的 Properties 对象。 |
getObjectType() | 返回目标对象类型(Properties.class )。 |
isSingleton() | 返回是否为单例(继承自 FactoryBean )。 |
setEnvironment(Environment env) | 设置 Environment 对象(用于变量替换,如 ${...} )。 |
setLoader(Class<? extends YamlLoader> loader) | 指定自定义的 YAML 加载器(默认 DefaultYamlLoader )。 |
3. 启动时的三个核心过程详解
3.1 Loading from Yaml
- 过程描述:加载 YAML 文件到内存。
- 实现细节:
- 资源定位:通过
setResources()
指定的路径(如classpath:config.yml
)获取资源。 - 流读取:使用
Resource
接口读取文件内容为InputStream
。 - 依赖 SnakeYAML:通过
Yaml
类解析 YAML 流为 Java 对象(如Map
)。
- 资源定位:通过
3.2 Merging Document
- 过程描述:合并多个 YAML 文档或嵌套结构。
- 实现细节:
- 多文档支持:YAML 支持多文档(通过
---
分隔),每个文档会被解析为独立的Map
。 - 合并逻辑:
- 将每个文档的
Map
转换为Properties
。 - 后续文档的键会覆盖前序文档的同名键。
- 将每个文档的
- 嵌套键处理:将嵌套结构(如
server.port
)转换为.
分隔的扁平键。
- 多文档支持:YAML 支持多文档(通过
3.3 Loaded 1 Document from YAML resource
- 过程描述:成功加载并解析一个 YAML 文档。
- 实现细节:
- 单文档解析:若资源中只有一个 YAML 文档,直接解析为
Properties
。 - 日志输出:Spring 会打印类似
Loaded 1 document from YAML resource
的日志,表明成功加载。
- 单文档解析:若资源中只有一个 YAML 文档,直接解析为
4. 完整流程示例
// 1. 创建 YamlPropertiesFactoryBean 实例
YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();// 2. 设置资源路径(支持多个文件)
yamlFactory.setResources(new ClassPathResource("config1.yml"), new ClassPathResource("config2.yml"));// 3. 转换为 Properties 对象
Properties properties = yamlFactory.getObject();// 4. 获取配置值
String serverPort = properties.getProperty("server.port"); // 合并后的值
5. 关键代码片段
// YamlPropertiesFactoryBean 的核心逻辑(简化版)
public class YamlPropertiesFactoryBean extends PropertiesFactoryBean {private YamlProcessor yamlProcessor = new DefaultYamlProcessor();@Overrideprotected Properties createProperties() throws IOException {Properties props = new Properties();for (Resource resource : getResources()) {Yaml yaml = new Yaml();// 解析 YAML 文件为 Map 列表List<Object> documents = yaml.loadAll(resource.getInputStream()).toList();for (Object document : documents) {if (document instanceof Map) {// 将 Map 转换为 Properties 并合并Map<String, Object> map = (Map<String, Object>) document;props.putAll(flattenMap(map, ""));}}}return props;}// 将嵌套 Map 转换为扁平的 Properties 键(如 server.port)private Map<String, Object> flattenMap(Map<String, Object> source, String parentKey) {Map<String, Object> flatMap = new HashMap<>();for (Map.Entry<String, Object> entry : source.entrySet()) {String key = parentKey.isEmpty() ? entry.getKey() : parentKey + "." + entry.getKey();if (entry.getValue() instanceof Map) {flatMap.putAll(flattenMap((Map<String, Object>) entry.getValue(), key));} else {flatMap.put(key, entry.getValue());}}return flatMap;}
}
6. 总结表格
过程/功能 | 描述 | 关键代码/方法 |
---|---|---|
Loading from Yaml | 加载 YAML 文件到内存,读取为 InputStream | Resource.getInputStream() ,Yaml.loadAll() |
Merging Document | 合并多个 YAML 文档或嵌套结构为扁平的 Properties | flattenMap() 方法处理嵌套键,props.putAll() 合并多个文档 |
Loaded 1 Document | 成功解析一个 YAML 文档并输出日志 | Yaml.loadAll() 返回单个文档,Spring 内部日志机制 |
依赖库 | 需要 SnakeYAML 库支持 | org.yaml.snakeyaml.Yaml |
适用场景 | 手动加载 YAML 配置文件,或需将 YAML 转换为 Properties 对象的场景 | @Value 、Environment 注入,或自定义配置合并逻辑 |
7. 注意事项
- 多文档覆盖规则:后加载的文档会覆盖前序文档的同名键。
- 嵌套键限制:不支持键名包含
.
的情况(会被错误解析)。 - Spring Boot 集成:Spring Boot 2.x 默认使用
Jackson
的 YAML 支持,需显式引入snakeyaml
依赖。
通过以上分析,可以清晰理解 YamlPropertiesFactoryBean
的工作原理及应用场景。
YamlPropertiesFactoryBean 类详解
1. 类概述
YamlPropertiesFactoryBean
是 Spring Framework 中用于将 YAML 文件 转换为 Properties
对象的工具类。它继承自 PropertiesFactoryBean
,并基于 SnakeYAML 库实现 YAML 解析功能。
2. 核心功能
- YAML 到 Properties 转换:将 YAML 文件中的配置转换为扁平化的
Properties
对象(键值对形式)。 - 支持嵌套结构:自动将 YAML 的嵌套键(如
server.port
)转换为Properties
的点分隔键(如server.port=8080
)。
3. 使用场景
- 在 Spring 旧版本(如 Spring Framework 5.x)中手动加载 YAML 配置。
- 需要将 YAML 文件转换为
Properties
对象进行后续处理(如合并配置、动态加载)。
4. 依赖说明
需要引入 SnakeYAML 依赖:
<!-- Maven -->
<dependency><groupId>org.yaml</groupId><artifactId>snakeyaml</artifactId><version>1.33</version> <!-- 根据版本选择 -->
</dependency>
5. 核心代码与使用示例
5.1 基本用法
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import java.util.Properties;public class YamlExample {public static void main(String[] args) {// 1. 创建 YamlPropertiesFactoryBean 实例YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();// 2. 设置 YAML 文件路径(例如 classpath 下的 config.yml)yamlFactory.setResources(new ClassPathResource("config.yml"));// 3. 转换为 Properties 对象Properties properties = yamlFactory.getObject();// 4. 获取配置值System.out.println(properties.getProperty("server.port")); // 输出:8080}
}
5.2 配置文件示例(config.yml
)
server:port: 8080
app:name: "MyApp"version: 1.0.0
5.3 转换后的 Properties 结果
server.port=8080
app.name=MyApp
app.version=1.0.0
6. 关键方法与属性
方法/属性 | 说明 |
---|---|
setResources | 设置 YAML 文件的资源路径(如 ClassPathResource 、FileSystemResource )。 |
getObject() | 返回转换后的 Properties 对象。 |
setSingleton | 是否将生成的 Properties 对象标记为单例(默认 true )。 |
7. 注意事项
-
嵌套键的处理:
- YAML 的嵌套结构会被自动转换为
.
分隔的键名(如server.port
)。 - 如果 YAML 中有特殊字符(如
:
或#
),需注意转义。
- YAML 的嵌套结构会被自动转换为
-
与 Spring Boot 的集成:
- Spring Boot 2.x+ 默认使用
Jackson
的 YAML 支持(jackson-dataformat-yaml
),而非SnakeYAML
。 - 若需兼容旧版,需显式引入
snakeyaml
依赖。
- Spring Boot 2.x+ 默认使用
-
替代方案:
- 在 Spring Boot 中,推荐使用
@Value
或@ConfigurationProperties
直接绑定 YAML 配置。
- 在 Spring Boot 中,推荐使用
8. 完整配置示例(Spring 配置 Bean)
@Configuration
public class AppConfig {@Beanpublic Properties yamlProperties() {YamlPropertiesFactoryBean yamlFactory = new YamlPropertiesFactoryBean();yamlFactory.setResources(new ClassPathResource("application.yml"));return yamlFactory.getObject();}
}
9. 总结表格
功能 | 说明 |
---|---|
YAML 解析 | 依赖 SnakeYAML 库,将 YAML 转换为 Properties 对象。 |
嵌套键处理 | 自动将 server.port 转换为 server.port=8080 。 |
适用场景 | Spring 旧版本手动加载 YAML 配置,或需要 Properties 对象的场景。 |
依赖管理 | 需引入 snakeyaml 依赖(Spring Boot 2.x+ 默认使用 Jackson)。 |
替代方案 | Spring Boot 推荐使用 @ConfigurationProperties 或 Environment 注入。 |
10. 常见问题
- Q: 使用时出现
ClassNotFoundException: org.yaml.snakeyaml.Yaml
?- A: 缺少 SnakeYAML 依赖,需添加
snakeyaml
依赖。
- A: 缺少 SnakeYAML 依赖,需添加
- Q: YAML 嵌套结构未正确转换?
- A: 确保 YAML 格式正确,键名无空格或特殊字符。
- Q: 如何在 Spring Boot 中直接使用?
- A: 推荐通过
@Value("${key}")
或Environment
获取值,无需手动调用YamlPropertiesFactoryBean
。
- A: 推荐通过
通过以上步骤,可以灵活使用 YamlPropertiesFactoryBean
实现 YAML 配置的加载与转换。