SpringBoot 2.3.1升级后@Value注解无法读取application.yml配置值
问题背景
现有测试类代码如下:
class TestClass( @Value("\${s3.published.bucket}") private val publishedBucketName: String ) { }
项目使用SpringBoot 2.1.8.RELEASE时运行状态正常,所有测试用例均可通过;升级SpringBoot版本至2.3.1.RELEASE后出现异常:@Value注解无法从src/main目录下的application.yml配置文件中读取s3.published.bucket对应的配置值。
对应application.yml配置内容如下:
s3: region: ${s3_region:eu-central-1} published: bucket: ${published_content_bucket:intermediate-bucket-nprd} draft: bucket: ${draft_content_bucket:nprd-draft-data}
已尝试的排查操作均未解决问题:
- 将
application.yml移动到src/test/resources文件夹下 - 给测试类添加
@SpringBootTest注解
测试运行抛出的核心错误日志如下:
org.junit.jupiter.api.extension.ParameterResolutionException: Failed to resolve parameter [java.lang.String publishedBucketName] in executable [public com.alefeducation.content.service.ContentBrowserTest(java.lang.String)] at org.junit.jupiter.engine.execution.ExecutableInvoker.resolveParameter(ExecutableInvoker.java:221) ... Caused by: java.lang.NoClassDefFoundError: org/springframework/integration/endpoint/Pausable ... Caused by: java.lang.ClassNotFoundException: org.springframework.integration.endpoint.Pausable at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ...
问题根因
报错和配置文件读取逻辑无关,核心原因是Spring上下文启动阶段就发生了类加载失败:
- SpringBoot 2.3.x版本升级了依赖的Spring Integration版本到5.3.x,
org.springframework.integration.endpoint.Pausable是Spring Integration 5.3版本才新增的接口。当前项目类路径下的Spring Integration版本低于5.3,缺少该类,触发ClassNotFoundException。 - SpringBoot 2.3版本新增了构造函数绑定的校验逻辑,将
@Value写在测试类主构造函数上的写法,会触发该校验逻辑,校验过程中扫描类路径时发现缺失上述类,直接中断Spring上下文初始化。上下文未完成启动,自然无法完成@Value的参数注入,最终抛出参数解析失败的异常。 - 移动配置文件、单纯加
@SpringBootTest注解都没有解决类缺失的核心问题,因此无效。
可行解决方案
- 对齐Spring Integration依赖版本:如果项目中直接或间接依赖了Spring Integration组件,将
spring-integration-core的版本升级到5.3.2.RELEASE(和SpringBoot 2.3.1.RELEASE官方匹配的版本)即可。如果是第三方依赖传递引入了旧版本,可以在构建配置中排除旧版本传递依赖,或强制指定符合要求的版本,由SpringBoot官方依赖管理自动维护版本兼容性。 - 移除无用依赖:如果项目完全没有使用Spring Integration相关功能,直接在依赖配置中排除
spring-integration-core的传递依赖,避免构造函数校验逻辑扫描到相关类路径触发类加载。 - 调整注入写法避开构造函数校验:将主构造函数注入改为类内部属性注入,绕开2.3版本新增的构造函数绑定检测逻辑,示例代码如下:
@SpringBootTest class TestClass { @Value("\${s3.published.bucket}") private lateinit var publishedBucketName: String // 测试用例逻辑 }
内容的提问来源于stack exchange,提问作者Yash zala
相关产品推荐
相关产品推荐

