Spring Boot AutoConfigure provides auto-configuration capabilities that automatically configure Spring applications based on jar dependencies present on the classpath
—
Master complex conditional logic in Spring Boot AutoConfigure.
For comprehensive conditional annotation reference, see Conditions Reference.
@Configuration
@ConditionalOnClass(DataSource.class)
@ConditionalOnProperty(prefix = "app.database", name = "enabled")
@ConditionalOnMissingBean(DataSource.class)
public class DatabaseConfiguration {
// All conditions must match
}@Configuration
@Conditional(DatabaseConditions.class)
public class StorageConfiguration {
// Configuration
}
static class DatabaseConditions extends AnyNestedCondition {
DatabaseConditions() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnProperty(name = "database.type", havingValue = "mysql")
static class MySQLEnabled {}
@ConditionalOnProperty(name = "database.type", havingValue = "postgresql")
static class PostgreSQLEnabled {}
}public class OnDatabaseTypeCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(
ConditionContext context,
AnnotatedTypeMetadata metadata) {
String dbType = context.getEnvironment()
.getProperty("database.type");
if ("mysql".equals(dbType)) {
return ConditionOutcome.match(
ConditionMessage.forCondition("OnDatabaseType")
.found("database type").items(dbType)
);
}
return ConditionOutcome.noMatch(
ConditionMessage.forCondition("OnDatabaseType")
.didNotFind("mysql database type").atAll()
);
}
}Order conditions from fastest to slowest:
@Configuration
@ConditionalOnClass(DataSource.class) // Fast
@ConditionalOnProperty("app.enabled") // Fast
@ConditionalOnBean(DataSource.class) // Slower
public class OptimizedConfiguration {
// Conditions evaluated in order
}static class AllConditions extends AllNestedConditions {
AllConditions() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnProperty("feature.enabled")
static class FeatureEnabled {}
@ConditionalOnClass(name = "com.example.SomeClass")
static class ClassPresent {}
}static class NoneConditions extends NoneNestedConditions {
NoneConditions() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnProperty("feature.disabled")
static class FeatureDisabled {}
@ConditionalOnClass(name = "com.example.ConflictingClass")
static class ConflictingClassPresent {}
}@Test
void testConditionMatches() {
contextRunner
.withPropertyValues("feature.enabled=true")
.run(context -> {
assertThat(context).hasBean("featureService");
});
}
@Test
void testConditionDoesNotMatch() {
contextRunner
.withPropertyValues("feature.enabled=false")
.run(context -> {
assertThat(context).doesNotHaveBean("featureService");
});
}