Spring Boot 3中使用@Autoconfiguration创建带参数Prototype Bean的问题
Spring Boot 3 @AutoConfiguration下原型Bean创建问题解决方案
问题根源
@AutoConfiguration默认启用proxyBeanMethods = false,此时配置类不会被Spring代理。直接调用配置类中的prototypeComponent()方法时,只是普通Java方法调用,返回的是手动new的对象,不会经过Spring容器的Bean生命周期管理,也就无法生成受容器管控的原型Bean。而Spring Boot 2的@Configuration默认proxyBeanMethods = true,方法调用会被代理,每次调用都会生成新的原型Bean并交由容器管理。
解决方案(无需使用ApplicationContext.getBean)
方案1:显式开启配置类代理
直接给@AutoConfiguration设置proxyBeanMethods = true,恢复Spring Boot 2的代理行为,原代码逻辑可直接复用:
@AutoConfiguration(proxyBeanMethods = true) public class TestPrototypeConfiguration { @Bean public SingletonComponent singletoneComponent() { return new SingletonComponent(this::prototypeComponent); } @Bean @Scope(value = BeanDefinition.SCOPE_PROTOTYPE) public PrototypeComponent prototypeComponent(int value) { return new PrototypeComponent(value); } }
注意:此方式会关闭@AutoConfiguration默认的性能优化(避免代理类生成),若自动配置逻辑复杂,需权衡性能影响。
方案2:使用ObjectProvider传递参数获取原型Bean
利用Spring的ObjectProvider接口,通过getObject(Object... args)方法传递参数,获取受容器管理的原型Bean:
- 修改
SingletonComponent,注入ObjectProvider<PrototypeComponent>:
@RequiredArgsConstructor public class SingletonComponent { private final ObjectProvider<PrototypeComponent> prototypeProvider; public void test() { for (int i = 0; i < 5; i++) { // 每次调用都会生成新的、受容器管理的原型Bean PrototypeComponent component = prototypeProvider.getObject(i); } } }
- 调整配置类,注入
ObjectProvider并传递给SingletonComponent:
@AutoConfiguration public class TestPrototypeConfiguration { @Bean public SingletonComponent singletoneComponent(ObjectProvider<PrototypeComponent> prototypeProvider) { return new SingletonComponent(prototypeProvider); } @Bean @Scope(value = BeanDefinition.SCOPE_PROTOTYPE) public PrototypeComponent prototypeComponent(int value) { return new PrototypeComponent(value); } }
方案3:自定义Spring管理的工厂类
创建受Spring管控的工厂类,封装原型Bean的创建逻辑,避免直接暴露BeanFactory调用:
- 定义工厂类:
@Component public class PrototypeComponentFactory { private final BeanFactory beanFactory; // 构造注入BeanFactory public PrototypeComponentFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; } public PrototypeComponent create(int value) { return beanFactory.getBean(PrototypeComponent.class, value); } }
- 修改
SingletonComponent依赖工厂类:
@RequiredArgsConstructor public class SingletonComponent { private final PrototypeComponentFactory factory; public void test() { for (int i = 0; i < 5; i++) { PrototypeComponent component = factory.create(i); } } }
- 配置类调整:
@AutoConfiguration public class TestPrototypeConfiguration { @Bean public SingletonComponent singletoneComponent(PrototypeComponentFactory factory) { return new SingletonComponent(factory); } @Bean @Scope(value = BeanDefinition.SCOPE_PROTOTYPE) public PrototypeComponent prototypeComponent(int value) { return new PrototypeComponent(value); } }
内容的提问来源于stack exchange,提问作者Demid Demidov
相关产品推荐
相关产品推荐

