Why an auto-configuration did not fire
Read the condition evaluation report instead of guessing which annotation is missing.
Open this lesson in the learning hubKey points
- Every auto-configuration class carries conditions. When one does not apply, Spring records why - it does not discard the reason.
- Start the application with
--debug, or setdebug=true, and Boot prints the condition evaluation report: positive matches, negative matches, and exclusions. - The most common cause is
@ConditionalOnMissingBeanbacking off because you defined a bean of that type yourself, often indirectly through another configuration class. - The second most common is ordering. Conditions are evaluated in auto-configuration order, so a bean defined by a later class is not yet visible to an earlier condition - which is what
@AutoConfigureBeforeand@AutoConfigureAfterexist to fix. - User configuration is always processed before auto-configuration, so your own
@Beanreliably wins. That is the whole back-off contract. - In Boot 3 an auto-configuration is registered in
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. The oldspring.factoriesentry is ignored, and a starter that still uses it simply never loads.
Example
// Registered in:
// src/main/resources/META-INF/spring/
// org.springframework.boot.autoconfigure.AutoConfiguration.imports
// containing one fully-qualified class name per line.
@AutoConfiguration(after = DataSourceAutoConfiguration.class)
@ConditionalOnClass(AuditWriter.class)
@EnableConfigurationProperties(AuditProperties.class)
public class AuditAutoConfiguration {
// Backs off entirely if the application declares its own AuditWriter.
@Bean
@ConditionalOnMissingBean
AuditWriter auditWriter(DataSource dataSource, AuditProperties props) {
return new JdbcAuditWriter(dataSource, props.getTableName());
}
// Only when the property is present AND set to true.
@Bean
@ConditionalOnProperty(prefix = "audit", name = "async", havingValue = "true")
AuditDispatcher asyncDispatcher(AuditWriter writer) {
return new AsyncAuditDispatcher(writer);
}
}
/*
* java -jar app.jar --debug prints, for the class above:
*
* Positive matches:
* AuditAutoConfiguration matched:
* - @ConditionalOnClass found required class AuditWriter (OnClassCondition)
*
* Negative matches:
* AuditAutoConfiguration#asyncDispatcher:
* - @ConditionalOnProperty (audit.async=true) did not find property (OnPropertyCondition)
*
* That second block is the answer to "why is my bean missing" - no guessing needed.
*/
Spring already knows why a bean is missing; --debug prints the reason, and the answer is nearly always a back-off or an ordering problem.
This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Spring Boot course, and every lesson in it is listed on the Spring Boot contents page.