@ConditionalOnBean无法与JdbcTemplate.class一起使用

时间:2019-06-21 10:02:38

标签: java spring spring-boot

我有一些弹簧组件:

@Component
@ConditionalOnBean(value={JdbcTemplate.class})
public class DictionaryHandler implements Handler {

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public DictionaryHandler(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    //some methods
}

在调试中,我看到创建了JdbcTemplate bean: enter image description here

但是,我的bean没有创建,它没有进入构造函数。但为什么? Bean JdbcTemplate存在,但我的bean没有创建。

条件是否起作用?如果缺少DictionaryHandler,我不想创建JdbcTemplate。没有这个,我会得到一个错误。

3 个答案:

答案 0 :(得分:2)

您仅应在自动配置类上使用@ConditionalOnBean(否则未指定顺序)

  

该条件只能匹配到目前为止应用程序上下文已处理的bean定义,因此,强烈建议仅在自动配置类上使用此条件。如果候选bean可能是由另一种自动配置创建的,请确保使用此条件的豆在此之后运行。

由于您的JdbcTemplate bean是在JdbcTemplateAutoConfiguration类中定义的,因此我假设JdbcTemplateAutoConfiguration被标记为@Configuration

在这种情况下,您可以通过config来确保bean的实例化:

@Configuration
@AutoConfigureAfter(JdbcTemplateAutoConfiguration.class)
public class DicationaryHandlerConfiguration {

    @Bean
    @ConditionalOnBean(JdbcTemplate.class)
    public DictionaryHandler handler(JdbcTemplate jdbcTemplate) {
         return new DictionaryHandler(jdbcTemplate)
    }

}

public class DictionaryHandler implements Handler {

    private final JdbcTemplate jdbcTemplate;

    public DictionaryHandler(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    //some methods
}

答案 1 :(得分:1)

来自Annotation Type ConditionalOnBean

  

该条件只能匹配到目前为止应用程序上下文已处理的bean定义,因此,强烈建议仅在自动配置类上使用此条件。如果候选bean可能是由另一种自动配置创建的,请确保使用此条件的候选bean在之后运行。

在您的情况下,问题是在处理配置类之前尝试创建DictionaryHandler bean,并且考虑到JdbcTemplate bean尚未位于DI容器中,因此您的DictionaryHandler尚未存在被实例化。
一种解决方法是在与DictionaryHandler相同的配置类中初始化JdbcTemplate
另外,您可以使用其他配置类,但必须使用@DependsOn注释。

一个例子:

@Component
@ConditionalOnBean(name = "bean1")
class AnotherBean {
}

@Configuration
class Config {
    @Bean
    public Object bean1() {
        return new Object();
    }
}

在上一个示例中,AnotherBean不会被创建,但是会这样:

@Configuration
class Config {
    @Bean
    public Object bean1() {
        return new Object();
    }

    @Bean
    @ConditionalOnBean(name = "bean1")
    public AnotherBean anotherBean() {
        return new AnotherBean();
    }
}

答案 2 :(得分:1)

查看ConditionalOnBean的文档。它运行一次,并且如果尚未创建所需的Bean,则不会触发。 Bean创建的顺序很重要。您可以尝试使用@Order批注来降低组件的优先级,或者增加包含JdbcTemplate bean的配置/组件类的优先级。