I have some spring component:
@Component
@ConditionalOnBean(value={JdbcTemplate.class})
public class DictionaryHandler implements Handler {
private final JdbcTemplate jdbcTemplate;
@Autowired
public DictionaryHandler(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
//some methods
}
In debug, I see, that JdbcTemplate bean was created:
enter image description here
But, my bean not created.It doesn't go into the constructor. But why? Bean JdbcTemplate is exist, but my bean not created.
Does the condition work wrong? I don't want create DictionaryHandler if JdbcTemplate is missing. Without this I get an error.
3 Answers 3
You should use @ConditionalOnBean on auto configuration classes only (otherwise the order is unspecified)
The condition can only match the bean definitions that have been processed by the application context so far and, as such, it is strongly recommended to use this condition on auto-configuration classes only. If a candidate bean may be created by another auto-configuration, make sure that the one using this condition runs after.
Since your JdbcTemplate bean is defined inside JdbcTemplateAutoConfiguration class so I assume that JdbcTemplateAutoConfiguration is marked with @Configuration.
In that case, you can ensure the instantiate of your bean by config:
@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
}
Comments
Check the documentation for ConditionalOnBean. It runs once and if the bean it requires not yet created - it will not trigger. The order of bean creation matters. You can try to lower priority of your component with @Order annotation or increase priority of you configuration/component class which holds JdbcTemplate bean.
Comments
From Annotation Type ConditionalOnBean:
The condition can only match the bean definitions that have been processed by the application context so far and, as such, it is strongly recommended to use this condition on auto-configuration classes only. If a candidate bean may be created by another auto-configuration, make sure that the one using this condition runs after.
In your case, the problem is DictionaryHandler bean is attempted to be created before processing the configuration class and given that JdbcTemplate bean is not yet in DI container, your DictionaryHandler is not getting instantiated.
One workaround could be to initialize DictionaryHandler in the same configuration class as JdbcTemplate.
Also, you can use different configuration class, but you'll have to use @DependsOn annotation.
An example:
@Component
@ConditionalOnBean(name = "bean1")
class AnotherBean {
}
@Configuration
class Config {
@Bean
public Object bean1() {
return new Object();
}
}
In the previous example AnotherBean will not be created, but it will be in this way:
@Configuration
class Config {
@Bean
public Object bean1() {
return new Object();
}
@Bean
@ConditionalOnBean(name = "bean1")
public AnotherBean anotherBean() {
return new AnotherBean();
}
}
3 Comments
take out my beans like in the separate starter and already in it to use autoconfiguration?
DictionaryHandlercreated when you remove the conditional?DictionaryHandlerwas created succesfully