Java @ConditionalOnBean无法使用JdbcTemplate.class

Java @ConditionalOnBean无法使用JdbcTemplate.class,java,spring,spring-boot,Java,Spring,Spring Boot,我有一些弹簧组件: @Component @ConditionalOnBean(value={JdbcTemplate.class}) public class DictionaryHandler implements Handler { private final JdbcTemplate jdbcTemplate; @Autowired public DictionaryHandler(JdbcTemplate jdbcTemplate) { th

我有一些弹簧组件:

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

    private final JdbcTemplate jdbcTemplate;

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

    //some methods
}
在debug中,我看到了JDBCTemplatebean的创建:

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

这种情况是否有问题?如果缺少JdbcTemplate,我不想创建DictionaryHandler。如果没有这个,我会得到一个错误。

来自:

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

在您的例子中,问题是在处理配置类之前尝试创建DictionaryHandler bean,并且假设JDBCTemplatebean还没有在DI容器中,那么DictionaryHandler就没有得到实例化。 一种解决方法是在与JdbcTemplate相同的配置类中初始化DictionaryHandler。 此外,您可以使用不同的配置类,但必须使用@DependsOn注释

例如:

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

@Configuration
class Config {
    @Bean
    public Object bean1() {
        return new Object();
    }
}
在前面的示例中,不会创建另一个Bean,但它将采用以下方式:

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

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

检查文档中的ConditionalOnBean。它运行一次,如果所需的bean尚未创建,它将不会触发。创建bean的顺序很重要。您可以尝试使用@Order注释降低组件的优先级,或者增加保存JdbcTemplate bean的配置/组件类的优先级。

您应该在自动配置类上使用,否则顺序是未指定的

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

由于jdbctemplatebean是在JdbcTemplateAutoConfiguration类中定义的,所以我假设JdbcTemplateAutoConfiguration用@Configuration标记

在这种情况下,您可以通过配置确保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
}

您删除条件时是否创建了DictionaryHandler?@AdhikaSetyaPramudita,是的,DictionaryHandler创建成功。请告诉我,我可以像在单独的启动程序中一样取出我的bean,并在其中使用自动配置?如何在开始时保持业务逻辑?对不起,我没听清你的问题,请您澄清一下,您在单独的starter中取出我的bean并在其中使用自动配置是什么意思?我想他的意思是:如果您有不同的模块和配置类,并将它们作为依赖项一起放在spring starter中,会怎么样?如果那不是他要问的,那就是我要问的,因为我正面临着这个问题。这两个bean具有不同的依赖关系,我无法控制它们的加载顺序。DependsOn和Order注释似乎不起作用。如果两个bean位于不同的配置文件和不同的代码库中,我如何保证顺序?