Spring原型作用域@Configuration构造函数@Value注入二次获取Bean报错原因
问题根本原因解析
根源:@Configuration默认代理机制与原型作用域的冲突
@Configuration注解默认proxyBeanMethods = true,属于Full模式配置类,Spring会为其生成CGLIB动态代理子类,核心作用是拦截类内部的@Bean方法调用,保证同一个@Bean方法多次调用返回的是同一个Bean实例。- 你为该类额外设置了
ConfigurableBeanFactory.SCOPE_PROTOTYPE作用域,要求每次getBean都生成新的类实例。
两次调用表现不同的原因
- 第一次调用
getBean(cfg.class)时,Spring处于配置类初始化的正式流程,会正常解析构造函数上的@Value("${xx}")注解,从application.properties读取对应值注入,因此运行正常。 - 第二次调用
getBean(cfg.class)时,因为是原型作用域需要生成新的代理类实例,此时CGLIB代理的实例化增强逻辑不会处理构造函数上的@Value注解,而是直接尝试从Spring容器中查找String类型的Bean作为构造参数注入,你的容器中没有注册String类型的Bean,因此抛出找不到对应Bean的错误。
两种修复方案生效的原因
- 替换为
@Component:@Component修饰的类属于Lite模式配置类,不会生成用于增强@Bean方法的CGLIB代理,每次实例化都会走普通Bean的依赖注入流程,能够正常解析@Value注解获取配置值。 - 添加
proxyBeanMethods = false:将配置类从Full模式切换为Lite模式,关闭方法代理特性,此时配置类的实例化逻辑和普通@Component类完全一致,因此可以正常解析构造函数的@Value注入。
内容的提问来源于stack exchange,提问作者Nicolai Nikolai
相关产品推荐
相关产品推荐

