您的位置:首页 > 移动开发

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类的定义。
@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
{
。。。
}
     不知道读者看到这里是被饶晕了,还是有种恍然大悟的感觉呢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息