Spring实现原理分析(二十五).Spring Boot如何把application.*中的配置数据转换成对象
2017-12-02 14:21
1046 查看
大家好!用过spring boot的人应该都知道“application.properties”和“application.yml”这两个配置文件吧,最常见的就是在这两个文件里面配置数据库连接信息。那么,今天我要向大家揭秘,spring boot是何时加载它们,以及如何应用配置文件的过程。
一. 何时加载application.*
spring boot的启动是由SpringApplication负责的,其中有一个很重要的run(String... args)方法。在run方法中有一个步骤是预准备环境对象,即ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners, ApplicationArguments)方法。该方法会通知所有已注册的事件监听器(ApplicationListener),通知它们环境对象(Environment)已经创建了,可以为它添加属性源(PropertySource)了。对于Environment没有概念的朋友,可以看我之前的博客。
配置文件事件监听器(ConfigFileApplicationListener)收到这个通知后做出回应,就把"application.properties"和"application.yml"中的内容转换成属性源添加到环境对象。那么,配置文件事件监听器又是从哪冒出来的呢?它被配置在autoconfigure's jar包里的spring.factories文件中,很多跟boot相关的jar包里都包含这个文件。在执行run(String...
args)之前,spring就已把这个事件监听器注册到bean工厂(BeanFactory)。
二. 把application.*中的配置数据输送到哪些对象呢?
把配置数据输送到被@ConfigurationProperties注解的类,这些类的类名往往是这样的“xxxxxxProperties ”,比如“WebMvcProperties”。我看下WebMvcProperties类的定义。
注解的prefix属性值是"spring.mvc",这个意思就是把application.*中所有前缀是spring.mvc的配置数据绑定到WebMvcProperties的属性,换句话说,就是WebMvcProperties持有所有关于spring mvc的配置。
@ConfigurationProperties注解本身的功能我就不介绍了,大家可以百度下,支持松散命名,支持jsr303校验。比如说,WebMvcProperties中某个属性被jsr303校验器注解了,那么从application.*中把配置数据绑定到属性前,会先对配置值执行校验。可能大家又会有个疑问,是谁负责把application.*中的配置数据输送到对象呢,这个行为发生在什么时候?
三. 谁负责把application.*中的配置数据输送到对象,何时输送。
执行输送任务的是ConfigurationPropertiesBindingPostProcessor(一个bean后处理器),在创建bean对象过程中的初始化bean步骤之前发生。那么,ConfigurationPropertiesBindingPostProcessor又是被谁注册到bean工厂的呢?答案是@EnableConfigurationProperties,我们看下这个注解的定义。
ConfigurationPropertiesBindingPostProcessorRegistrar:负责注册ConfigurationPropertiesBindingPostProcessor,这个bean后处理器的作用前面说了。
ConfigurationPropertiesBeanRegistrar : 负责注册配置类依赖的被@ConfigurationProperties注解的类,比如DispatcherServletConfiguration依赖WebMvcProperties,于是乎WebMvcProperties也被注册到bean工厂了。
那么,为什么会发生上述操作呢,答案是spring boot默认定义一些被@EnableConfigurationProperties注解的配置类,比如DispatcherServletConfiguration,我们看下它的定义。
一. 何时加载application.*
spring boot的启动是由SpringApplication负责的,其中有一个很重要的run(String... args)方法。在run方法中有一个步骤是预准备环境对象,即ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners, ApplicationArguments)方法。该方法会通知所有已注册的事件监听器(ApplicationListener),通知它们环境对象(Environment)已经创建了,可以为它添加属性源(PropertySource)了。对于Environment没有概念的朋友,可以看我之前的博客。
配置文件事件监听器(ConfigFileApplicationListener)收到这个通知后做出回应,就把"application.properties"和"application.yml"中的内容转换成属性源添加到环境对象。那么,配置文件事件监听器又是从哪冒出来的呢?它被配置在autoconfigure's jar包里的spring.factories文件中,很多跟boot相关的jar包里都包含这个文件。在执行run(String...
args)之前,spring就已把这个事件监听器注册到bean工厂(BeanFactory)。
二. 把application.*中的配置数据输送到哪些对象呢?
把配置数据输送到被@ConfigurationProperties注解的类,这些类的类名往往是这样的“xxxxxxProperties ”,比如“WebMvcProperties”。我看下WebMvcProperties类的定义。
@ConfigurationProperties(prefix = "spring.mvc") public class WebMvcProperties { 。。。省略 }
注解的prefix属性值是"spring.mvc",这个意思就是把application.*中所有前缀是spring.mvc的配置数据绑定到WebMvcProperties的属性,换句话说,就是WebMvcProperties持有所有关于spring mvc的配置。
@ConfigurationProperties注解本身的功能我就不介绍了,大家可以百度下,支持松散命名,支持jsr303校验。比如说,WebMvcProperties中某个属性被jsr303校验器注解了,那么从application.*中把配置数据绑定到属性前,会先对配置值执行校验。可能大家又会有个疑问,是谁负责把application.*中的配置数据输送到对象呢,这个行为发生在什么时候?
三. 谁负责把application.*中的配置数据输送到对象,何时输送。
执行输送任务的是ConfigurationPropertiesBindingPostProcessor(一个bean后处理器),在创建bean对象过程中的初始化bean步骤之前发生。那么,ConfigurationPropertiesBindingPostProcessor又是被谁注册到bean工厂的呢?答案是@EnableConfigurationProperties,我们看下这个注解的定义。
@Import(EnableConfigurationPropertiesImportSelector.class) public @interface EnableConfigurationProperties { 。。。省略 }这个注解本身又被@Import(EnableConfigurationPropertiesImportSelector.class)注解了,被导入的EnableConfigurationPropertiesImportSelector是一个导入选择器,这个类的作用是导入“ConfigurationPropertiesBeanRegistrar.class”和“ConfigurationPropertiesBindingPostProcessorRegistrar.class”,被导入的这两个类有一个共同的特点,它们都实现了ImportBeanDefinitionRegistrar接口,也就是说被导入的这两个类本身的作用是往bean工厂注册bean定义对象的。
ConfigurationPropertiesBindingPostProcessorRegistrar:负责注册ConfigurationPropertiesBindingPostProcessor,这个bean后处理器的作用前面说了。
ConfigurationPropertiesBeanRegistrar : 负责注册配置类依赖的被@ConfigurationProperties注解的类,比如DispatcherServletConfiguration依赖WebMvcProperties,于是乎WebMvcProperties也被注册到bean工厂了。
那么,为什么会发生上述操作呢,答案是spring boot默认定义一些被@EnableConfigurationProperties注解的配置类,比如DispatcherServletConfiguration,我们看下它的定义。
@EnableConfigurationProperties(WebMvcProperties.class) protected static class DispatcherServletConfiguration { 。。。 }不知道读者看到这里是被饶晕了,还是有种恍然大悟的感觉呢!
相关文章推荐
- Spring实现原理分析(二十五).Spring Boot如何把application.*中的配置数据转换成对象
- Spring3.1.0实现原理分析(三).配置数据
- springboot实现将配置文件的属性转换成一个对应的pojo对象的属性
- Spring3.1.0实现原理分析(三).配置数据
- Spring3.1.0实现原理分析(一).类型转换
- SpringBoot下如何配置实现跨域请求?
- Spring3.1.0实现原理分析(十).AOP代理对象执行拦截过程
- Spring3.1.0实现原理分析(九).AOP创建代理对象的过程
- SpringBoot下如何配置实现跨域请求?
- SpringBoot下如何配置实现跨域请求?
- SpringBoot下如何配置实现跨域请求?
- Spring3.1.0实现原理分析(一).类型转换
- SpringBoot下如何配置实现跨域请求?
- springboot如何读取配置文件(application.yml)中的属性值
- SpringBoot下如何配置实现跨域请求?
- SpringBoot下如何配置实现跨域请求?
- 全面解析SpringBoot自动配置的实现原理
- SpringBoot下如何配置实现跨域请求?
- Spring3.1.0实现原理分析(十六).MVC数据绑定器
- SpringBoot下如何配置实现跨域请求?