Auto-configuration
@EnableAutoConfiguration, conditional beans, spring.factories, auto-config internals
Auto-configuration
1. Definition
The Spring Boot auto-configuration mechanism automatically configures application Spring beans based on libraries on the classpath, existing bean definitions, and properties. The @EnableAutoConfiguration annotation (part of @SpringBootApplication) activates this system. The essence of auto-configuration is that developers should not need to manually configure what the framework can infer — the "convention over configuration" principle.
For example, if spring-boot-starter-data-jpa and an H2 driver are on the classpath, Spring Boot automatically creates a DataSource, EntityManagerFactory, and TransactionManager.
2. Core Concepts
@EnableAutoConfiguration
The @SpringBootApplication meta-annotation contains three things:
@SpringBootConfiguration // = @Configuration
@EnableAutoConfiguration // activates auto-config
@ComponentScan // component scanning
public @interface SpringBootApplication {}
@EnableAutoConfiguration starts the auto-configuration search. In Spring Boot 3.x, the META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports file contains registered auto-configuration classes.
Conditional Annotations
Auto-configuration classes use @Conditional* annotations to control when they activate:
| Annotation | Condition |
|---|---|
@ConditionalOnClass |
Given class is on the classpath |
@ConditionalOnMissingClass |
Given class is NOT on the classpath |
@ConditionalOnBean |
Given bean exists in the context |
@ConditionalOnMissingBean |
Given bean does NOT exist (user override) |
@ConditionalOnProperty |
Property has a given value |
@ConditionalOnWebApplication |
Web application context |
@ConditionalOnResource |
Given resource is available |
@ConditionalOnExpression |
SpEL expression is true |
The "Back Off" Principle
Auto-configuration backs off when a developer defines their own bean. This is implemented with @ConditionalOnMissingBean:
@AutoConfiguration
@ConditionalOnClass(DataSource.class)
public class DataSourceAutoConfiguration {
@Bean
@ConditionalOnMissingBean // If developer defined a DataSource, this doesn't run
public DataSource dataSource(DataSourceProperties props) {
return props.initializeDataSourceBuilder().build();
}
}
spring.factories vs AutoConfiguration.imports
| Version | Registration mechanism |
|---|---|
| Spring Boot 2.x | META-INF/spring.factories (EnableAutoConfiguration key) |
| Spring Boot 3.x | META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports |
Spring Boot 3.x still supports spring.factories for backward compatibility, but the new approach is recommended.
3. Practical Usage
Excluding Auto-configuration
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class MyApp { ... }
Or via property:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
Overriding Auto-configuration with Your Own Bean
@Configuration
public class MyDataSourceConfig {
@Bean
public DataSource dataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:postgresql://localhost/mydb");
ds.setUsername("admin");
return ds;
}
}
// DataSourceAutoConfiguration backs off due to @ConditionalOnMissingBean
Debug: Which Auto-configs Are Active?
# application.properties
debug=true
This prints the Conditions Evaluation Report at startup:
- Positive matches: active auto-configuration classes
- Negative matches: inactive (condition not met)
- Unconditional classes: configurations without conditions
Actuator Endpoint
management.endpoints.web.exposure.include=conditions
The /actuator/conditions endpoint returns the same information in JSON format at runtime.
4. Code Examples
Simple Auto-configuration Class
@AutoConfiguration
@ConditionalOnClass(ObjectMapper.class)
@EnableConfigurationProperties(JsonProperties.class)
public class JsonAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public ObjectMapper objectMapper(JsonProperties props) {
ObjectMapper mapper = new ObjectMapper();
if (props.isIndentOutput()) {
mapper.enable(SerializationFeature.INDENT_OUTPUT);
}
return mapper;
}
}
ConfigurationProperties for Properties
@ConfigurationProperties(prefix = "app.json")
public class JsonProperties {
private boolean indentOutput = false;
public boolean isIndentOutput() { return indentOutput; }
public void setIndentOutput(boolean v) { this.indentOutput = v; }
}
app.json.indent-output=true
Custom Auto-configuration Module (Library)
my-library/
├── src/main/java/com/example/
│ └── MyLibraryAutoConfiguration.java
└── src/main/resources/META-INF/spring/
└── org.springframework.boot.autoconfigure.AutoConfiguration.imports
The .imports file contents:
com.example.MyLibraryAutoConfiguration
@AutoConfiguration Ordering
@AutoConfiguration(
after = DataSourceAutoConfiguration.class,
before = JpaRepositoriesAutoConfiguration.class
)
public class MyAutoConfiguration { ... }
5. Trade-offs
| Aspect | Advantage | Disadvantage |
|---|---|---|
| Automatic configuration | Fast development, less boilerplate | "Magic" — hard to understand what happens |
| Convention over configuration | Uniform project structure | More overrides needed for custom requirements |
| @ConditionalOnMissingBean | User can override anything | If you don't know about it, you can't use it |
| debug=true | Full transparency | Very verbose output |
| Custom auto-config module | Reusable libraries | Extra complexity, harder testing |
When NOT Auto-configuration?
- Very custom configuration: if many overrides are needed, explicit config is cleaner
- Performance-critical startup: many auto-config classes slow down startup
- Library development: carefully design the conditional logic
6. Common Mistakes
❌ Auto-config Override Not Working
// BAD — @Bean method in the @SpringBootApplication class
// Component scan may run before auto-config
@SpringBootApplication
public class MyApp {
@Bean
public DataSource dataSource() { ... } // May not override!
}
// GOOD — separate @Configuration class
@Configuration
public class MyDataSourceConfig {
@Bean
public DataSource dataSource() { ... }
}
❌ Exclude Typo
// BAD — non-existent class, silently ignored
@SpringBootApplication(exclude = {NonExistentAutoConfiguration.class})
// GOOD — excludeName string when class is not on classpath
@SpringBootApplication(excludeName = "com.example.SomeAutoConfiguration")
❌ @ConditionalOnBean Ordering Problem
// BAD — @ConditionalOnBean does not guarantee ordering
// If the bean is created by another auto-config, ordering matters
@AutoConfiguration
public class MyConfig {
@Bean
@ConditionalOnBean(DataSource.class) // DataSource may not exist yet!
public MyRepo repo(DataSource ds) { ... }
}
// GOOD — explicit ordering
@AutoConfiguration(after = DataSourceAutoConfiguration.class)
public class MyConfig { ... }
❌ @ComponentScan in Auto-config Library
// BAD — auto-config library should NOT use @ComponentScan
// Application packages may be scanned too
@AutoConfiguration
@ComponentScan("com.example") // Dangerous!
public class LibraryAutoConfig { ... }
// GOOD — explicit @Bean definitions
@AutoConfiguration
public class LibraryAutoConfig {
@Bean
public MyService myService() { return new MyService(); }
}
7. Deep Dive
Auto-configuration Loading Process
SpringApplication.run()starts@EnableAutoConfiguration→AutoConfigurationImportSelectoractivates- Reads
.importsfiles (and legacyspring.factories) - Collects all auto-configuration classes
- Filters by
@Conditional*(condition evaluation) - Registers remaining classes as bean definitions
@AutoConfiguration(after/before)determines ordering
@Conditional Internals
Every @Conditional* annotation has a Condition interface implementation behind it:
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
ConditionContext provides access to:
- BeanDefinitionRegistry — existing bean definitions
- Environment — properties and profiles
- ResourceLoader — classpath resources
- ClassLoader — classpath class checking
Auto-configuration vs @Configuration
| Aspect | @AutoConfiguration | @Configuration |
|---|---|---|
| Loading | From .imports file |
Component scan / @Import |
| Ordering | after/before attributes |
No guaranteed order |
| Purpose | Framework/library defaults | Application-specific config |
| @ConditionalOnMissingBean | Typical (back-off) | Rare |
Custom Condition Implementation
public class OnProductionCondition implements Condition {
@Override
public boolean matches(ConditionContext ctx, AnnotatedTypeMetadata metadata) {
String env = ctx.getEnvironment().getProperty("app.env");
return "production".equals(env);
}
}
@Configuration
@Conditional(OnProductionCondition.class)
public class ProductionOnlyConfig { ... }
GraalVM Native and Auto-configuration
With Spring Boot 3.x native image support, auto-configuration is evaluated at compile-time (AOT processing). This results in faster startup but runtime @Conditional evaluation is not available.
8. Interview Questions
How does Spring Boot auto-configuration work?
@EnableAutoConfigurationactivatesAutoConfigurationImportSelector, which reads.importsfiles, collects auto-config classes, evaluates@Conditional*annotations, and registers matching bean definitions.What is the role of @ConditionalOnMissingBean? If a developer already defined a bean of the same type, auto-configuration backs off. This allows overriding without excluding the entire auto-config class.
How can you find out which auto-configurations are active?
debug=trueproperty → Conditions Evaluation Report in the log. Or/actuator/conditionsendpoint.What is the difference between spring.factories and the .imports file?
spring.factoriesis the Spring Boot 2.x approach (key-value pairs). The.importsfile is the 3.x standard (one class per line). Both register auto-config classes.How do you write your own auto-configuration?
@AutoConfigurationclass +@Conditional*annotations +.importsfile underMETA-INF/spring/. Use@ConditionalOnMissingBeanfor back-off logic.Why shouldn't you use @ComponentScan in an auto-config library? Because it could scan application packages too, registering unexpected beans. Use explicit
@Beandefinitions in auto-config libraries.What is auto-configuration ordering and why is it important?
@AutoConfiguration(after/before)controls loading order. Important when one auto-config bean depends on another (e.g., DataSource needed for JPA auto-config).
9. Glossary
| Term | Meaning |
|---|---|
| @EnableAutoConfiguration | Annotation that activates auto-config |
| @AutoConfiguration | Marks an auto-configuration class (Boot 3.x) |
| @ConditionalOnClass | Condition: class is on the classpath |
| @ConditionalOnMissingBean | Condition: no such bean → back-off logic |
| @ConditionalOnProperty | Condition: property value |
| spring.factories | Legacy (2.x) auto-config registration file |
| AutoConfiguration.imports | Modern (3.x) auto-config registration file |
| AutoConfigurationImportSelector | Class that reads and filters auto-configs |
| Conditions Evaluation Report | Debug output of active/inactive auto-configs |
| Back-off | Auto-config stepping back when developer defined a bean |
| Convention over configuration | Framework-level defaults, minimal config |
| AOT processing | Compile-time auto-config evaluation (GraalVM native) |
10. Cheatsheet
Auto-configuration activation:
@SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan
Registration:
Boot 3.x: META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
Boot 2.x: META-INF/spring.factories (EnableAutoConfiguration key)
Key @Conditional annotations:
@ConditionalOnClass(Foo.class) on classpath
@ConditionalOnMissingBean(Foo.class) no such bean (back-off)
@ConditionalOnProperty(name="x") property exists/value
@ConditionalOnBean(Foo.class) bean exists
Back-off pattern:
@Bean
@ConditionalOnMissingBean
public Foo foo() { ... } // developer can override
Exclusion:
@SpringBootApplication(exclude = {FooAutoConfiguration.class})
spring.autoconfigure.exclude=com.example.FooAutoConfiguration
Debug:
debug=true → Conditions Evaluation Report
/actuator/conditions → JSON of running conditions
Ordering:
@AutoConfiguration(after = A.class, before = B.class)
Common mistakes:
✗ @Bean override in @SpringBootApplication class
✗ @ConditionalOnBean ordering problem
✗ @ComponentScan in auto-config library
✗ Using spring.factories in Boot 3.x (deprecated)
🎮 Games
10 questions