情景描述
最近新搭建了一个项目,从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属性类自动加载配置文件中的值
springboot属性类自动加载配置文件中的值,如Person类加载在yml中配置的name,age等属性值,可以通过如下步骤获取: 类上添加@ConfigurationProperties注解,p ...
-
SpringBoot加载子模块配置文件的方法
这两天开始学习SpringBoot框架,按照官方的文档,很轻易地就把单模块的项目启动了,但在使用maven搭建多模块的时候遇到了子模块配置文件没有加载的问题 项目架构是这样的 zero |-ws |- ...
-
Spring详解(十)加载配置文件
在项目中有些参数经常需要修改,或者后期可能会有改动时,那我们最好把这些参数放到properties文件中,在源代码中读取properties里面的配置,这样后期只需要改动properties文件即可, ...
-
spring加载配置文件
spring加载配置文件 1.把applicationContext.xml直接放在WEB-INF/classes下,spring会采用默认的加载方式2.采用在web.xml中配置ContextLoa ...
-
spring-自动加载配置文件\使用属性文件注入
在上一篇jsf环境搭建的基础上 , 加入spring框架 , 先看下目录结构 src/main/resources 这个source folder 放置web项目所需的主要配置,打包时,会自动打包到W ...
随机推荐
-
C# 解析JSON格式数据
JSON简介 JSON(全称为JavaScript ObjectNotation) 是一种轻量级的数据交换格式.它是基于JavaScript语法标准的一个子集.JSON采用完全独立于语言的文本格式,可 ...
-
android 制作自定义标题栏
1.在AndroidManifest.xml设置主题 android:theme="@android:style/Theme.NoTitleBar.Fullscreen" 2.在l ...
-
黄聪:Discuz!X/数据库操作方法、DB::table、C::t
函数 功能 DB::table($tablename) 获取正确带前缀的表名,转换数据库句柄, DB::delete($tablename, 条件,条数限制) 删除表中的数据 DB::insert($ ...
-
SignalR 2.0入门
下载已完成的项目 本教程展示如何使用那么 SignalR 创建一个实时聊天应用程序.你会那么 SignalR 添加一个空的 ASP.NET web 应用程序,创建一个 HTML 页面发送并显示消息. ...
-
android SharedPreferences 使用
除了SQLite数据库外,SharedPreferences也是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值 对数据,通常用来存储一些简单的配置信息.其存储位置在/dat ...
-
操,escape sequence的输入方法我以前找过一次,这次又忘了,又找了一次,记下来,
所有的手册和回答都没有说,都是用 echo -e '\e[22;22m,如果不愿意使用echo -e,也可以 输入CvC[[22:22m 不要再忘记了.
-
HTML5可以省略结束标记的元素
HTML5可以省略结束标记的元素 1.dd 2.dt 3.li 4.p 5.optgroup 6.option 7.rt 8.rp 9.thread 10.tfoot 11.tr 12.td 13.t ...
-
double转换为二进制
arctan 在verilog 里是1qn或2qn格式,所以要把浮点数转换成1qn格式 1.dec2bin(十进制整数变为二进制) Convert decimal to binary number i ...
-
PTA——判断胖瘦
PTA 7-40 到底是不是太胖了 #include<stdio.h> #include<math.h> int main() { ,N; scanf("%d&quo ...
-
从消费者角度评估RestFul的意义
相关博文: 从消费者角度评估RestFul的意义 SpringBoot 构建RestFul API 含单元测试 REST是目前业界相当火热的术语,似乎发布的API不带个REST前缀,你都不好意思和别人 ...