• SpringBoot加载配置文件(@PropertySource@importSource@Value)


    情景描述

    最近新搭建了一个项目,从Spring迁到了Springboot,为了兼容Spring加载配置文件的风格,所以还想把PropertyPlaceholderConfigurer放在.xml文件里面,然后通过@importSource来加载.xml文件将配置加载到spring环境中,通过@value或者PropertyUtil来引入对应配置的值。于是发现了以下问题,并根据这些问题进行了问题拓展。

    问题描述

    1.在.xml引入PropertyPlaceholderConfigurer时,若项目中存在@PropertySource注解,@ConfigurationProperties可以正常加载PropertySource中的配置(启动时发现Bean正常),但是@Value会在启动时报错解析不了占位符;若@ConfigurationProperties加载的是.xml中配置文件的值,则也为空。

    2.在使用PropertyUtil(由.xml加载配置)时发现,在通过.xml加载配置的这个方法上,public static 变量在@Configuration的配置类通过PropertyUtil获取配置值时PropertyUtil还未加载(值为null),在其他@Component(包括@Controller)中是可以正常获取到值(说明已经加载)。

    解决方案&原理分析

    问题1:

    其中@PropertySource注解管理的所有配置文件相当于一个PropertyPlaceholderConfigurer,只不过是Springboot自己管理的,而.xml中的PropertyPlaceholderConfigurer又是一个,这就会出现多个PropertyPlaceholderConfigurer的问题(目测是由于先加载了@ImportSource中.xml的PropertyPlaceholderConfigurer导致该问题),多PropertyPlaceholderConfigurer问题原因如下:

    在spring bean装配时,一个PropertyPlaceholderConfigurer就是一个后置处理器BeanFactoryPostProcessor。在装配完PropertyPlaceholderConfigurer之后,就会触发org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(Collection<? extends BeanFactoryPostProcessor>, ConfigurableListableBeanFactory)方法,代码如下:

    复制代码
    /**
     * Invoke the given BeanFactoryPostProcessor beans.
     */
    private void invokeBeanFactoryPostProcessors(
            Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
    
        for (BeanFactoryPostProcessor postProcessor : postProcessors) {
            postProcessor.postProcessBeanFactory(beanFactory);
        }
    }
    复制代码

    每调用完一个BeanFactoryPostProcessor之后,就会去解析所有的bean中引用properties的占位符,这时就会出现占位符不能解析的问题(不能解析的占位在后面的BeanFactoryPostProcessor中,也就是PropertyPlaceholderConfigurer实例)。

    而在使用@Value时,由于使用了占位符,而.xml中的PropertyPlaceholderConfigurer先加载解析占位符但是该配置未存在,所以会报错占位符解析失败。

    而使用@ConfigurationProperties时,并没有使用占位符,所以如果是在@PropertySource中的配置可以正常加载

    但是我个人理解@ConfigurationProperties加载配置是用的@PropertySource的PropertyPlaceholderConfigurer,所以如果配置不是用@PropertySource加载,则加载结果为null(建议配套使用)

    解决方法:

    <property name="ignoreUnresolvablePlaceholders" value="true"/>

    加上上面的一行,表示可以忽略未解析到的占位符。这样就不会报错。

    问题2:

    我理解@Confituration标识的配置类是在@ImportSource加载.xml之前文件开始加载的,所以它的static值在从PropertyUtil获取值时,PropertyUtil并没有加载配置,所以都为空,但是@Component也即bean加载是在@ImportSource之后的,所以static变量可以获取到正常值。
    经过试验,我发现@Value在@Configuration标识的配置类中是可以正常获取到.xml加载的值的,这样表明@Value应该是在@ImportSource之后注入的了。

    附:

    @PropertySource API:Resource location wildcards (e.g. **/*.properties) are not permitted; each location must evaluate to exactly one .properties resource.(不允许使用资源位置通配符(例如** / *.属性);每个位置必须只评估一个.properties资源)

    如果对我上面的分析存在异议欢迎讨论啊,希望相互提高。

    转载请注明:https://www.cnblogs.com/fnlingnzb-learner/p/11067338.html

  • 相关阅读:
    转载 centos7安装kafka_2.11-1.0.0 新手入门(集群)
    Kafka得介绍与单节点部署
    MVC Areas
    Session如何保存在sql数据库中
    AsposeCell特定格式表格
    DataTable数据修改,换列
    A1095 Cars on Campus (30 分)
    A1075 PAT Judge (25 分)
    A1016 Phone Bills (25 分)
    A1082 Read Number in Chinese (25 分)
  • 原文地址:https://www.cnblogs.com/fnlingnzb-learner/p/11067338.html
Copyright © 2020-2023  润新知