Why this matters
- Custom auto-configuration lets teams share BookStore client libraries across microservices with zero manual bean registration.
- Conditions prevent beans from loading in the wrong environment — a Redis cache bean should not start when Redis is absent.
@ConfigurationPropertiescombined with conditions creates type-safe, environment-aware configuration.
Building a custom auto-configuration
Suppose BookStore integrates with an external recommendation engine:
@ConfigurationProperties(prefix = "bookstore.recommendations")
public record RecommendationProperties(
boolean enabled,
String apiUrl,
Duration timeout
) {}
@AutoConfiguration
@ConditionalOnClass(RecommendationClient.class)
@ConditionalOnProperty(
prefix = "bookstore.recommendations",
name = "enabled",
havingValue = "true"
)
@EnableConfigurationProperties(RecommendationProperties.class)
public class RecommendationAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public RecommendationClient recommendationClient(RecommendationProperties props) {
return RecommendationClient.builder()
.baseUrl(props.apiUrl())
.timeout(props.timeout())
.build();
}
}
Register in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:
com.example.bookstore.recommendations.RecommendationAutoConfiguration
Consumers add the library JAR and set properties — the client bean appears automatically.
Condition types for custom config
@ConditionalOnClass— Feature available only when a library is present.@ConditionalOnMissingBean— User can override with their own@Bean.@ConditionalOnProperty— Toggle features viaapplication.yml.@ConditionalOnProfile— Environment-specific beans (staging,prod).@ConditionalOnBean— Activate only when another bean exists.
Custom condition class
For logic conditions cannot express:
public class OnWeekdayCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
DayOfWeek day = LocalDate.now().getDayOfWeek();
return day != DayOfWeek.SATURDAY && day != DayOfWeek.SUNDAY;
}
}
@Configuration
@Conditional(OnWeekdayCondition.class)
public class WeekdayBatchConfig {
@Bean
public Job weekdayInventorySync() { ... }
}
Rare in BookStore APIs but useful for scheduled maintenance jobs.
@ConfigurationProperties validation
@ConfigurationProperties(prefix = "bookstore.recommendations")
@Validated
public record RecommendationProperties(
boolean enabled,
@NotBlank @URL String apiUrl,
@NotNull Duration timeout
) {}
Invalid YAML fails at startup:
bookstore:
recommendations:
enabled: true
api-url: not-a-url # BindValidationException
timeout: 5s
Multiple property sources
@Configuration
@PropertySource("classpath:bookstore-defaults.properties")
@EnableConfigurationProperties(BookStoreProperties.class)
public class BookStoreConfig { }
Library defaults ship in bookstore-defaults.properties; consumers override in application.yml.
Ordering custom auto-config
@AutoConfiguration(after = DataSourceAutoConfiguration.class)
@ConditionalOnBean(DataSource.class)
public class BookAuditAutoConfiguration {
@Bean
public AuditRepository auditRepository(DataSource ds) { ... }
}
Ensures the DataSource exists before creating audit infrastructure.
Testing conditional beans
@SpringBootTest
@TestPropertySource(properties = "bookstore.recommendations.enabled=true")
class RecommendationAutoConfigurationTest {
@Autowired(required = false)
RecommendationClient client;
@Test
void clientCreatedWhenEnabled() {
assertNotNull(client);
}
}
Use @SpringBootTest with property overrides to verify conditions match as expected.
Feature flags in BookStore
bookstore:
features:
recommendations: true
price-alerts: false
@Service
@ConditionalOnProperty(name = "bookstore.features.recommendations", havingValue = "true")
public class RecommendationService { ... }
Deploy the same JAR everywhere; feature flags control which beans activate per environment.
Quick recall
Everything you need if you only revisit this box.
@ConditionalOn*gates bean registration on classpath, properties, profiles, and existing beans.- Custom auto-config lives in a library JAR registered via
AutoConfiguration.imports. @ConfigurationProperties+@Validatedprovides type-safe, fail-fast configuration.@ConditionalOnMissingBeanlets consumers override library defaults with their own beans.- Test conditions with
@SpringBootTestand@TestPropertySource. - Feature flags via
@ConditionalOnPropertyenable per-environment capability toggling.
Test yourself
Answer these before moving on — recall is what makes it stick.