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:
附:
@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
SpringBoot加载配置文件(@PropertySource@importSource@Value)的更多相关文章
- Springboot 加载配置文件源码分析
Springboot 加载配置文件源码分析 本文的分析是基于springboot 2.2.0.RELEASE. 本篇文章的相关源码位置:https://github.com/wbo112/blogde ...
- SpringBoot加载配置文件的几种方式
首先回忆一下在没有使用SpringBoot之前也就是传统的spring项目中是如何读取配置文件,通过I/O流读取指定路径的配置文件,然后再去获取指定的配置信息. 传统项目读取配置方式 读取xml配置文 ...
- SpringBoot 加载配置文件
1.application.properties或application.yaml是SpringBoot默认的配置文件. 可以通过@Value注解 配合 ${......}来读取配置在属性文件中的内容 ...
- SpringBoot是如何加载配置文件的?
前言 本文针对版本2.2.0.RELEASE来分析SpringBoot的配置处理源码,通过查看SpringBoot的源码来弄清楚一些常见的问题比如: SpringBoot从哪里开始加载配置文件? Sp ...
- springboot加载外部配置文件
网上搜集和整理如下(自己已验证过) 1. war包在tomcat中加载外部配置文件 war包运行在独立tomcat下时,如何加载war包外部配置application.properties,以达到每次 ...
- springboot属性类自动加载配置文件中的值
springboot属性类自动加载配置文件中的值,如Person类加载在yml中配置的name,age等属性值,可以通过如下步骤获取: 类上添加@ConfigurationProperties注解,p ...
- SpringBoot加载子模块配置文件的方法
这两天开始学习SpringBoot框架,按照官方的文档,很轻易地就把单模块的项目启动了,但在使用maven搭建多模块的时候遇到了子模块配置文件没有加载的问题 项目架构是这样的 zero |-ws |- ...
- 微服务架构 | *2.3 Spring Cloud 启动及加载配置文件源码分析(以 Nacos 为例)
目录 前言 1. Spring Cloud 什么时候加载配置文件 2. 准备 Environment 配置环境 2.1 配置 Environment 环境 SpringApplication.prep ...
- Spring详解(十)加载配置文件
在项目中有些参数经常需要修改,或者后期可能会有改动时,那我们最好把这些参数放到properties文件中,在源代码中读取properties里面的配置,这样后期只需要改动properties文件即可, ...
随机推荐
- 【转】PostgreSQL与MySQL比较
转自:https://www.cnblogs.com/geekmao/p/8541817.html PostgreSQL与MySQL比较 特性 MySQL PostgreSQL 实例 通过执行 M ...
- [转]Vue中用props给data赋初始值遇到的问题解决
原文地址:https://segmentfault.com/a/1190000017149162 2018-11-28更:文章发布后因为存在理解错误,经@Kim09AI同学提醒后做了调整,在此深表感谢 ...
- Nginx返回固定json或者文本格式的方法
在系统还没有做集群的情况下,直接重启项目时刚好用户在使用的话,一般都会受到投诉,那么使用nginx返回类似“系统维护”的提示信息并且提前在应用上面做通知才是合适的做法 那么记录一下nginx里面的配置 ...
- 【错误解决】UnicodeDecodeError: 'gbk' codec can't decode byte 0xad in position 840: illegal multibyte sequence
原文来源:https://www.zhihu.com/question/22699590 编码问题错误,读入文件的时候指定编码即可. with open(fname, encoding='utf-8' ...
- 创建Observer
观察者 观察者作用就是监听事件, 然后对这个事件做出响应, 或者说任何响应时间的行为都是观察者 1. 在subscribe()方法中创建监听者 创建观察者最直接的方法就是在Observable的sub ...
- 在OpenShift 3.11环境开启多网络平面
1.整体架构 Multus CNI是OpenShift的容器网络接口(CNI)插件,可将多个网络接口附加到Pod. 通常,在OpenShift中,每个Pod仅具有一个网络接口(除了回送),Multus ...
- 记录一次TraceId的问题
多服务部署的时候,各个服务通过httpClient进行调用时候,有时候出现问题,需要进行追查.但是如果没有一个标记,就会很迷茫,特别是多个服务来回调用,就无法快速定位问题.这个时候一般是使用MDC的 ...
- phpspreadsheet 中文文档(六)读写文件+读取文件
2019年10月11日14:05:58 读写文件 从体系结构您已经知道,使用基本PhpSpreadsheet类无法对持久性存储进行读写.为此,PhpSpreadsheet提供读者和作家,这是实现\Ph ...
- Python的网页解析库-PyQuery
PyQuery库也是一个非常强大又灵活的网页解析库,如果你有前端开发经验的,都应该接触过jQuery,那么PyQuery就是你非常绝佳的选择,PyQuery 是 Python 仿照 jQuery 的严 ...
- kubernetes之kube-proxy运行机制分析
在kubernetes集群的每个node都会运行一个kube-proxy服务进程,这个进程可用看作Service的透明代理兼负载均衡器.其核心功能是将到某个Service的访问请求转发到后端的多个po ...