SpringBoot加载配置文件(@[email protected]@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之后注入的了。

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

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

原文地址:https://www.cnblogs.com/fnlingnzb-learner/p/11067338.html

时间: 2024-10-08 17:45:46

SpringBoot加载配置文件(@[email protected]@Value)的相关文章

Spring Boot加载配置文件的完整步骤

这篇文章主要给大家介绍了关于Spring Boot加载配置文件的完整步骤,文中通过示例代码介绍的非常详细,对大家的学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧 前言 本文针对版本2.2.0.RELEASE来分析SpringBoot的配置处理源码,通过查看SpringBoot的源码来弄清楚一些常见的问题比如: SpringBoot从哪里开始加载配置文件? SpringBoot从哪些地方加载配置文件? SpringBoot是如何支持yaml和proper

springboot属性类自动加载配置文件中的值

springboot属性类自动加载配置文件中的值,如Person类加载在yml中配置的name,age等属性值,可以通过如下步骤获取: 类上添加@ConfigurationProperties注解,prefix为yml中配置的属性名称,要想属性类生效得加上@Component注解 如果想要在yml中有对应类的提示,还需要添加如下依赖: yml书写如下: 如果是properties文件,则书写如下: 在yml中如果值中有特殊字符,需要转义可以用单引号包裹,默认是双引号 如果仅仅为类中的某个属性值赋

Spring4.1使用c3p0加载配置文件连接数据库,Access denied for user &#39;root&#39;@&#39;localhost&#39; 错误!

db.properties jdbc.user=root jdbc.password=admin jdbc.driverClass=com.mysql.jdbc.Driver jdbc.jdbcUrl=jdbc\:mysql\:///spring4 jdbc.initialPoolSize=5 jdbc.maxPoolSize=10 Spring.xml中 <context:property-placeholder location="classpath:db.properties&quo

shell加载配置文件

shell有不同的启动方式,根据启动方式的不同会加载不同的配置文件,从而配置不同的环境变量 我们比较常见的启动方式有: 1.通过linux控制台登录或者ssh方式,启动shell,这种情况为登录式启动shell 会依次加载/etc/environment, /etc/profile, ~/.bash_profile (或者~/.bash_login 或者 ~/.profile) 而~/.bash_profile中又会加载~/.bashrc,而~/.bashrc又加载  /etc/bashrc ,

Spring的classpath与classpath*通配符加载配置文件

classpath 与 classpath*以及通配符是怎么处理的 Spring加载Resource文件是通过ResourceLoader来进行的,那么我们就先来看看ResourceLoader的继承体系,让我们对这个模块有一个比较系统的认知. 首先,我们来看下ResourceLoader的源码 public interface ResourceLoader { /** Pseudo URL prefix for loading from the class path: "classpath:&

java加载配置文件

转载自http://blog.163.com/wb_zhaoyuwei/blog/static/183075439201261764454791/ 当我们自己的程序需要处理配置文件时(比如xml文件或properties文件),通常会遇到两个问题: (1)我的配置文件应该放在哪里? (2)怎么我的配置文件找不到了? 对于第一个问题,答案是:请将你的资源文件放在classpath里,如果资源文件在jar中,请将该jar文件也加到classpath里面. 对于第二个问题,就得看你是使用的是哪个类(C

【Nutch2.2.1源码分析之一】Nutch加载配置文件的方法

1.NutchConfiguration.java用于加载及获取Nutch的相关参数. Utility to create Hadoop Configurations that include Nutch-specific  resources. 即它会加载hadoop及nutch中的参数文件. 关键是2个create()方法,它加载了参数文件的同时,又返回了Configuration对象. 2.不带参数的create方法 public static Configuration create()

smarty加载配置文件和读取其中的参数

加载配置文件 在smarty中通过{config_load}加载配置文件. 属性: 参数名称 类型 必选参数 默认值 说明 file string Yes n/a 载入的配置文件名 section string No n/a 指定载入配置变量的段落 scope string no local 配置变量的作用范围,取值local, parent 或 global. local表示变量只能在当前模板的上下文中使用. parent表示变量可以在当前模板和父模板使用. global表示变量在任何地方都可

加载配置文件.properties,及面向接口编程的DaoFactory

1 package cn.itcast.usermng.dao; 2 3 import java.io.InputStream; 4 import java.util.Properties; 5 6 /** 7 * 通过配置文件得到dao实现类的名称! 8 * 通过类名称,完成创建类对象!(反射完成的!) 9 * @author cxf 10 * 11 */ 12 public class DaoFactory { 13 private static Properties props = nul