文章目录

  • 前言
  • SpringBoot中的源码分析
  • Spring中怎么使用yml作为配置文件
  • 1.添加支持解析YAML的库(可选)
  • 2.将properties文件转换为yml文件
  • 3. 配置解析application.yml文件的PropertySourcesPlaceholderConfigurer:
  • PropertySourcesPlaceholderConfigurer的作用


前言

推荐在项目中使用yml文件作为配置文件,因为yml可以配置对象,还可以单文件配置多环境。而传统properties配置多环境需要多文件。

YAML是JSON的超集,因此这是一种非常方便的格式,用于指定分层配置数据。它是所有编程语言的人性化数据序列化标准。YAML更易读,对于开发人员的读/写配置文件是有好处的。

YAML设计目标:

  1. YAML易于人类阅读。
  2. YAML数据在编程语言之间是可移植的。
  3. YAML匹配敏捷语言的本机数据结构。
  4. YAML具有一致的模型来支持通用工具。
  5. YAML支持单程处理。
  6. YAML具有表现力和可扩展性。
  7. YAML易于实施和使用。

SpringBoot中的源码分析

参考SpringBoot启动如何加载application.yml配置文件

  • @EnableAutoConfiguration : 帮你实现自动配置的类,SpringBoot工程启动时,会运行一个SpringFactoriesLoader这个类, 加载META-INF/spring.factories配置类 (已经开启的) , 通过SpringFactoriesLoader 中的load方法, 以for循环的方式 ,一个一个加载配置。
  • XxxAutoConfiguration: 自动配置类 : 给容器中添加组件。
  • XxxProperties : 封装了配置文件的中的相关属性 : 给组件赋值。

每一个XxxAutoConfiguration类里面都包含了很多组件bean , 条件成立后都会加载到容器中,这个组件的属性从XxxProperties类中获取 , XxxProperties类中的每一个属性的值, 又和properties进行绑定。

Spring中怎么使用yml作为配置文件

Spring从4.1版本开始就提供了对YAML的支持,所以从Spring4.1开始要使用yml作为配置文件很简单,具体操作步骤如下。

1.添加支持解析YAML的库(可选)

<!-- SpringBoot就是使用的SnakeYAML库进行YAML支持 -->
<dependency>
   <groupId>org.yaml</groupId>
   <artifactId>snakeyaml</artifactId>
   <version>1.17</version>
</dependency>

不知道为啥我亲测不导入这个库也行,但是Spring提供的YamlPropertiesFactoryBean和YamlMapFactoryBean都继承了Spring提供的YamlProcessor,且YamlProcessor需要依赖snakeyaml提供的Yaml类。

spring boot main方法加载某个类 springboot如何加载_spring boot

spring boot main方法加载某个类 springboot如何加载_配置文件_02

2.将properties文件转换为yml文件

可以使用“Convert YAML and Properties File”插件帮助我们快速将properties文件转换为yml文件,或将yml文件转换为properties文件。

首先要安装这个插件,Settings --> Plugins --> 搜索"Convert YAML and Properties File" --> Install。(我这个是已经安装成功了的截图)

spring boot main方法加载某个类 springboot如何加载_spring_03


然后选中要转换的文件,右键 --> convert。

spring boot main方法加载某个类 springboot如何加载_YAML_04


就自动转换好了。

spring boot main方法加载某个类 springboot如何加载_源码_05

3. 配置解析application.yml文件的PropertySourcesPlaceholderConfigurer:

有两种方式

  • 方式一:在Spring核心配置类中配置
//若在WebApplicationInitializer#getRootConfigClasses()中已声明该类是Spring核心配置类,此处就不必添加@Configuration注解
//@Configuration
@ComponentScan(basePackages = {"com.pxl.mvc"}, useDefaultFilters = true
    , excludeFilters = {@Filter(type = FilterType.ANNOTATION, classes = {Controller.class})})
//@PropertySource("classpath:application.properties")
public class RootConfig {
	@Bean
	public static PropertySourcesPlaceholderConfigurer properties() {
	  PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
	  YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
	  yamlPropertiesFactoryBean.setResources(new ClassPathResource("application.yml"));
	  propertySourcesPlaceholderConfigurer.setProperties(yamlPropertiesFactoryBean.getObject());
	  return propertySourcesPlaceholderConfigurer;
	}
}

注意:不能直接写为@PropertySource(“classpath:application.yml”),若这样写,结果是每一行被解析为一个k-v,因为该注解对应的解析器并不支持解析yml语法。

  • 方式二:在spring.xml的<context:property-placeholder />中配置
<context:annotation-config/>
<bean id="yamlProperties" class="org.springframework.beans.factory.config.YamlPropertiesFactoryBean">
    <property name="resources" value="classpath:application.yml"/>
</bean>
<context:property-placeholder properties-ref="yamlProperties"/>

PropertySourcesPlaceholderConfigurer的作用

  • 什么时候会创建propertySourcesPlaceholderConfigurer-bean?
// 从ContextLoaderListener#contextInitialized()开始分析
contextInitialized:107, ContextLoaderListener (org.springframework.web.context)
initWebApplicationContext:326, ContextLoader (org.springframework.web.context)
configureAndRefreshWebApplicationContext:444, ContextLoader (org.springframework.web.context)
refresh:41010, AbstractApplicationContext (org.springframework.context.support)
__refresh:523, AbstractApplicationContext (org.springframework.context.support)
invokeBeanFactoryPostProcessors:681, AbstractApplicationContext (org.springframework.context.support)
invokeBeanFactoryPostProcessors:154, PostProcessorRegistrationDelegate (org.springframework.context.support)
getBean:202, AbstractBeanFactory (org.springframework.beans.factory.support)
doGetBean:302, AbstractBeanFactory (org.springframework.beans.factory.support)
getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
getObject:306, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
createBean:482, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:510, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBeanInstance:1023, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
instantiateUsingFactoryMethod:1128, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
instantiateUsingFactoryMethod:588, ConstructorResolver (org.springframework.beans.factory.support)
instantiate:162, SimpleInstantiationStrategy (org.springframework.beans.factory.support)
invoke:498, Method (java.lang.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
//创建propertySourcesPlaceholderConfigurer-bean
properties:31, RootConfig (com.pxl.mvc.config)
  • 哪里会使用到我们注册的propertySourcesPlaceholderConfigurer-bean进行解析applicaiton.yml?
    (待续…)

YamlPropertiesFactoryBean将加载YAML做为Properties和YamlMapFactoryBean将加载YAML做为Map,详情可参考Spring Boot Features