PrepZone Logo
PrepZone

@Conditional and Custom @Configuration

Write your own auto-configuration with conditional annotations and @ConfigurationProperties.

Read these first

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.
  • @ConfigurationProperties combined with conditions creates type-safe, environment-aware configuration.
Classpath scanFind @AutoConfiguration classes
@Conditional checksOnClass, OnBean, OnProperty
Register beansOnly if conditions pass
Boot checks classpath and existing beans before creating defaults.

Building a custom auto-configuration

Suppose BookStore integrates with an external recommendation engine:

Java
@ConfigurationProperties(prefix = "bookstore.recommendations")
public record RecommendationProperties(
    boolean enabled,
    String apiUrl,
    Duration timeout
) {}
Java
@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:

Java
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 via application.yml.
  • @ConditionalOnProfile — Environment-specific beans (staging, prod).
  • @ConditionalOnBean — Activate only when another bean exists.

Custom condition class

For logic conditions cannot express:

Java
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

Java
@ConfigurationProperties(prefix = "bookstore.recommendations")
@Validated
public record RecommendationProperties(
    boolean enabled,
    @NotBlank @URL String apiUrl,
    @NotNull Duration timeout
) {}

Invalid YAML fails at startup:

Java
bookstore:
  recommendations:
    enabled: true
    api-url: not-a-url   # BindValidationException
    timeout: 5s

Multiple property sources

Java
@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

Java
@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

Java
@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

Java
bookstore:
  features:
    recommendations: true
    price-alerts: false
Java
@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 + @Validated provides type-safe, fail-fast configuration.
  • @ConditionalOnMissingBean lets consumers override library defaults with their own beans.
  • Test conditions with @SpringBootTest and @TestPropertySource.
  • Feature flags via @ConditionalOnProperty enable per-environment capability toggling.

Test yourself

Answer these before moving on — recall is what makes it stick.