Spring手动调用prototype Bean方法报参数对应类型Bean不存在问题问询
问题认知纠正
你的认知确实存在错误。Spring对所有标注@Bean的工厂方法,无论作用域是singleton还是prototype,默认都会尝试从Spring上下文中查找匹配的Bean来注入方法入参,不会因为是prototype就跳过参数依赖检查。
你在connectionFactoryManager中直接调用connectionFactory(serviceProps)属于配置类内部的普通方法调用,Spring不会干预这个调用的传参,但Spring本身会扫描到@Bean标注的connectionFactory方法,尝试校验这个Bean的依赖是否满足,因此会抛出找不到JmsServiceProps类型Bean的错误。
解决方案
你需要将批量创建的ConnectionFactory都纳入Spring上下文管理,这里提供两种可行方案:
方案1:通过ApplicationContext动态获取prototype Bean
保留connectionFactory的prototype Bean定义,调用getBean时手动传入参数,适合后续还需要动态创建不同参数的ConnectionFactory的场景:
@Configuration class JmsConfiguration( val props: JmsProperties, val applicationContext: ApplicationContext ) : JmsListenerConfigurer { @Bean fun connectionFactoryManager(): ConnectionFactoryManager { val connectionFactories = props.services.map { serviceProps -> // 动态传入serviceProps参数获取prototype实例 applicationContext.getBean("connectionFactory", serviceProps) as ConnectionFactory }.toList() return ConnectionFactoryManager(connectionFactories) } @Bean @Scope(BeanDefinition.SCOPE_PROTOTYPE) fun connectionFactory(@Autowired(required = false) serviceProps: JmsServiceProps): ConnectionFactory { val cf = MQConnectionFactory() // 基于serviceProps完成配置逻辑 return cf } override fun configureJmsListeners(registrar: JmsListenerEnpointRegistrar) { // 原有自定义监听器注册逻辑 } }
注意给方法参数加@Autowired(required = false),关闭Spring启动时的依赖校验,避免启动报错。
方案2:手动注册Bean到Spring上下文
去掉connectionFactory的@Bean注解,创建实例后手动注册到容器,更适合当前固定基于配置批量创建实例的场景:
@Configuration class JmsConfiguration( val props: JmsProperties, val beanFactory: ConfigurableListableBeanFactory ) : JmsListenerConfigurer { @Bean fun connectionFactoryManager(): ConnectionFactoryManager { val connectionFactories = props.services.mapIndexed { index, serviceProps -> val cf = createConnectionFactory(serviceProps) // 自定义Bean名称注册到上下文,方便后续其他组件按名称注入 beanFactory.registerSingleton("connectionFactory-$index", cf) cf }.toList() return ConnectionFactoryManager(connectionFactories) } // 作为普通工具方法,不需要@Bean注解 private fun createConnectionFactory(serviceProps: JmsServiceProps): ConnectionFactory { val cf = MQConnectionFactory() // 基于serviceProps完成配置逻辑 return cf } override fun configureJmsListeners(registrar: JmsListenerEnpointRegistrar) { // 原有自定义监听器注册逻辑 } }
后续其他组件可以通过@Qualifier("connectionFactory-{索引}")注入指定实例,或者通过List<ConnectionFactory>注入所有实例。
内容的提问来源于stack exchange,提问作者mr.nothing
相关产品推荐
相关产品推荐

