Spring Boot中RequestScope Bean属性为Null的Kotlin问题
Kotlin实现RequestScope Bean时属性获取为null的问题
环境
- Spring Boot 2.7.2
- Kotlin: 221-1.7.10-release-333-IJ5591.52
复现代码
@SpringBootApplication class AbcApplication fun main(args: Array<String>) { runApplication<AbcApplication>(*args) } @RestController class Home(val importantContext: ImportantContext) { @GetMapping fun index(): Any { return "toString: '${importantContext}' VS message: '${importantContext.importantMessage}'"; } } @Configuration class ImportantConfiguration { @Bean @RequestScope fun importantContext(): ImportantContext { return ImportantContext("important content") } } open class ImportantContext(var importantMessage: String?) { override fun toString(): String { return "ImportantContext(importantMessage=$importantMessage)" } }
问题现象
调用GET http://localhost:8080 返回结果:
toString: 'ImportantContext(importantMessage=important content)' VS message: 'null'
预期属性importantMessage的值应与toString输出一致,但实际获取为null。改用Java实现ImportantContext后可正常获取属性值。
原因分析
这是Spring作用域代理机制导致的:
- 标记
@RequestScope的Bean会被Spring生成CGLIB代理类,代理类继承原类,用于在请求作用域内管理Bean实例。 - Kotlin中,即使类被标记为
open,类内var/val属性的getter/setter方法默认是final的,无法被CGLIB代理类重写。 - 直接访问
importantMessage属性时,调用的是代理类的final getter方法,而代理类自身未初始化该属性,因此返回null。 toString()方法被显式override,属于open方法,代理类可重写它,最终会调用真实Bean实例的toString方法,因此能显示正确值。
解决方案
给ImportantContext类的importantMessage属性添加open修饰符,让其getter方法变为可重写,CGLIB代理就能正确转发属性访问到真实Bean实例:
open class ImportantContext(open var importantMessage: String?) { override fun toString(): String { return "ImportantContext(importantMessage=$importantMessage)" } }
内容的提问来源于stack exchange,提问作者otocon
相关产品推荐
相关产品推荐

