如何通过动态创建Spring bean的行为使@ConditionalOnMissingBean工作(例如:beanfactory寄存器)

时间:2019-05-05 03:56:33

标签: java spring spring-boot

我正在编写一个Spring Boot Starter,我想实现在Spring IOC中动态创建bean注入,并且可以使@ConditionalOnMissingBean在不创建默认bean的情况下生效。

我试图直接在配置类中编织beanfactory,并通过ConfigurableBeanFactory调用registerSingleton方法来动态创建bean,但是结果是错误的,@ ConditionalOnMissingBean无效。 @Bean可以,这应该与春季启动扫描@Configuration类和相应的@Bean方法有关,但是@Bean无法实现Bean的动态创建,因为我需要的Bean是根据配置的内容生成的文件,数量不确定,内容不确定。

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    this.beanFactory = beanFactory;
    ConfigurableBeanFactory configurableBeanFactory = (ConfigurableBeanFactory) beanFactory;
    while (iterator.hasNext()) {
    // Generate a bean based on the configuration
    ...
    SpringBean bean = ...
    configurableBeanFactory.registerSingleton(SpringBeanName, bean);
}

我希望如果动态创建bean,@ConditionalOnMissingBean仍然会生效。

1 个答案:

答案 0 :(得分:1)

API documentation中所述:

  

@Conditional批注可以通过以下任何一种方式使用:

     
      
  • 作为直接或间接使用@Component注释的任何类的类型级别注释,包括@Configuration类
  •   
  • 作为元注释,目的是组成自定义构造型注释
  •   
  • 作为任何@Bean方法上的方法级注释
  •   

这意味着它对启动后在ApplicationContext中注册的动态创建的bean无效。 因此,当您想实现类似的行为时,请尝试检查bean是否存在于ApplicationContext中,如下所示:

@Autowired
private ApplicationContext context;

...
context.getBeansOfType(YourType.class).isEmpty()

更新:

要摆脱该bean的默认配置时,需要排除它。有两种方法可以实现这一目标。通过将其定义为@SpringBootApplication(exclude = SomeConfig.class)来排除定义该bean的整个配置文件,或者在@ComponentScan上实现自己的排除过滤器。