1 @PropertySource 可以加载什么类型的资源文件?

@PropertySource 默认支持 properties 和 xml 类型的资源文件,都是直接通过 value 值来指定文件路径即可,默认使用的工厂为 ​​DefaultPropertySourceFactory​​。

1.1 DefaultPropertySourceFactory

DefaultPropertySourceFactory 使用的是ResourcePropertySource来加载资源,而 ResourcePropertySource 利用的是PropertiesLoaderUtil的loadProperties()方法,而loadProperties()底层是利用JDK自带的Properties类来完成配置的读取,不管是properties类型还是xml类型的文件。

1.2 Properties如何实现xml文件读取

xml 文件的读取是利用的是 Properties 自身的静态内部类 XmlSupport 来完成。

2 Spring 如何实现 yml 文件读取

我们都知道 SpringBoot 对于项目的配置文件,支持 properties 和 yaml 两种文件类型的读取,而 yaml 利用的是 snakeyaml 这个组件;所以在原生 Spring 项目中,也可以利用这个组件来完成 yaml类型文件的读取。

2.1 引入snakeyaml依赖

<!-- 支持spring读取yml文件作为配置源 -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>1.26</version>
</dependency>

2.2 自定义PropertySourceFactory 接口

/**
*
* @author winfun
* @date 2021/7/5 10:49 上午
**/
public class YmlPropertySourceFactory implements PropertySourceFactory {

@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {

YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
// 传入resource资源文件
yamlPropertiesFactoryBean.setResources(resource.getResource());
// 直接解析获得Properties对象
Properties properties = yamlPropertiesFactoryBean.getObject();
// 如果@PropertySource没有指定name,则使用资源文件的文件名
return new PropertiesPropertySource((name != null ? name : resource.getResource().getFilename()), properties);
}
}

2.3 在@PropertySource 注解指定factory属性值

/**
* yml格式的配置类
* @author winfun
* @date 2021/7/5 10:49 上午
**/
@Data
@Component
public class YmlSchoolProperties {

@Value("${yml.school.name}")
private String name;
@Value("${yml.school.location}")
private String location;
@Value("${yml.school.level}")
private String level;
}

/**
*
* @author winfun
* @date 2021/7/5 11:34 上午
**/
@Configuration
@ComponentScan(basePackages = {"com.github.howinfun.demo.ioc.propertysource.yml"})
@PropertySource(value = "classpath:propertySource/school.yml",encoding = "UTF-8",factory = YmlPropertySourceFactory.class)
public class YmlConfiguration {
}

2.4 yaml文件&读取结果

yml:
school:
name: 佛山大学
location: 佛山
level: 本科
/**
* 启动类
* @author winfun
* @date 2021/7/5 9:50 上午
**/
public class Application {

public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(YmlConfiguration.class);
YmlSchoolProperties ymlSchoolProperties = applicationContext.getBean(YmlSchoolProperties.class);
// YmlSchoolProperties(name=佛山大学, location=佛山, level=本科)
System.out.println(ymlSchoolProperties);
}
}