zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    帮人“解封微信”犯法?全国首例!判刑!
    热乎的校招面经试题解析——百度篇
    字节跳动入局在线教育:烧钱、亏钱
    TF-IDF 算法介绍
    Django ORM 常见查询条件
    Django中render和render_to_response的区别
    Python异步操作MongoDB --Motor的使用
    Java 如何抛出异常、自定义异常
    java项目中的classpath到底是什么
    maven里的modelVersion
  • 原文地址:https://www.cnblogs.com/fnlingnzb-learner/p/11067338.html
Copyright © 2011-2022 走看看