3

We´re working on multi-module project where each module is a cutom spring boot starter that holds several retryable tasks. (Using spring-retry)

In order to ensure that retry annotations are activated only once cross starters, a configuration bean is added to each starter auto configuration submodule:

 @EnableRetry
 @Configuration
 @ConditionalOnMissingBean(RetryConfiguration.class)
 public class StarterRetryAutoConfiguation {}

The solution is working as expected.

Question: What's the difference between @ConditionalOnSingleCandidate and @ConditionalOnMissingBean ?

I've read the Spring documentation more then once. However, I didn't get when and where should we use each one of them.

ConditionalOnSingleCandidate:

@Conditional that only matches when a bean of the specified class is already contained in the BeanFactory and a single candidate can be determined. The condition will also match if multiple matching bean instances are already contained in the BeanFactory but a primary candidate has been defined; essentially, the condition match if auto-wiring a bean with the defined type will succeed.

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.

ConditionalOnMissingBean:

@Conditional that only matches when no beans meeting the specified requirements are already contained in the BeanFactory. None of the requirements must be met for the condition to match and the requirements do not have to be met by the same bean.

Katy
  • 1,023
  • 7
  • 19

1 Answers1

1

We can use @ConditionalOnMissingBean if we want to load a bean only if a certain other bean is not in the application context:

@Configuration
class OnMissingBeanModule {
  @Bean
  @ConditionalOnMissingBean
  DataSource dataSource() {
    return new InMemoryDataSource();
  }
}

In this example, we’re only injecting an in-memory datasource into the application context if there is not already a datasource available. This is very similar to what Spring Boot does internally to provide an in-memory database in a test context.


We can use @ConditionalOnSingleCandidate if we want to load a bean only if a single candidate for the given bean class has been determined.

@Configuration
@ConditionalOnSingleCandidate(DataSource.class)
class OnSingleCandidateModule {
  ...
}

In this example, the condition matches if there is exactly one primary DataSource bean specified in your application context.

Jesus Zavarce
  • 1,729
  • 1
  • 17
  • 27