Mastering Spring Boot’s @Conditional: Dynamically Load Beans Based on Conditions
This guide explains the purpose and mechanics of Spring Boot's @Conditional annotation, shows its source definition, outlines usage forms, provides a complete example with custom Condition implementations for MySQL and Oracle beans, and lists the related derived conditional annotations available in Spring Boot.
Conditional Annotation @Conditional
@Conditional is a Spring Framework annotation (package org.springframework.context.annotation) that determines whether a class or method should be instantiated as a Bean based on one or more Condition implementations. It is heavily used in Spring Boot auto‑configuration to enable beans only when specific criteria are met, such as the presence of a class on the classpath.
Source Code Overview
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnClassCondition.class)
public @interface ConditionalOnClass {
// ...
}Usage Forms
Type level – can be placed on @Component or @Configuration classes.
Prototype level – used on meta‑annotations such as @ConditionalOnClass.
Method level – can annotate any @Bean method.
Note: @Conditional is not inherited; a subclass does not inherit conditions defined on its parent class.
Source Definition of @Conditional
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
// The attribute receives an array of classes that implement Condition
Class<? extends Condition>[] value();
}The associated Condition interface defines a single method:
@FunctionalInterface
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}If matches returns true, the annotated component is instantiated; otherwise it is skipped.
Practical Example
We demonstrate a scenario where a configuration property db.type determines which database‑specific bean is created.
db.type=mysqlTwo Condition implementations read this property:
public class MysqlCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String dbType = context.getEnvironment().getProperty("db.type");
return "mysql".equalsIgnoreCase(dbType);
}
} public class OracleCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String dbType = context.getEnvironment().getProperty("db.type");
return "oracle".equalsIgnoreCase(dbType);
}
}Both conditions produce beans that implement a common interface:
public interface DbConfigBean {
void printInfo();
} public class MysqlDbConfigBean implements DbConfigBean {
@Override
public void printInfo() {
System.out.println("I am Mysql!");
}
} public class OracleDbConfigBean implements DbConfigBean {
@Override
public void printInfo() {
System.out.println("I am Oracle!");
}
}The configuration class uses @Conditional on each @Bean method:
@Configuration
public class DbConfig {
@Bean
@Conditional(MysqlCondition.class)
public DbConfigBean mysql() {
return new MysqlDbConfigBean();
}
@Bean
@Conditional(OracleCondition.class)
public DbConfigBean oracle() {
return new OracleDbConfigBean();
}
}If both beans could exist simultaneously, the @Primary annotation would be needed to resolve ambiguity.
Service usage:
@Service
public class DbService {
@Autowired
private DbConfigBean configBean;
public void getDbInfo() {
configBean.printInfo();
}
}Unit test example:
@SpringBootTest
class DbServiceTest {
@Resource
private DbService dbService;
@Test
void getDbInfo() {
dbService.getDbInfo();
}
}Depending on the value of db.type, the appropriate bean prints its message.
Derived Conditional Annotations in Spring Boot
@ConditionalOnBean– active when a specific bean is present. @ConditionalOnClass – active when a class is on the classpath. @ConditionalOnCloudPlatform – active when a particular cloud platform is active. @ConditionalOnExpression – evaluates a SpEL expression. @ConditionalOnJava – checks the JVM version. @ConditionalOnJndi – looks up a JNDI location. @ConditionalOnMissingBean – active when a bean is absent. @ConditionalOnMissingClass – active when a class is missing. @ConditionalOnNotWebApplication – active for non‑web applications. @ConditionalOnProperty – active when a configuration property has a specific value. @ConditionalOnResource – active when a resource exists on the classpath. @ConditionalOnSingleCandidate – active when a single candidate bean is present or a primary bean is designated. @ConditionalOnWebApplication – active for web applications.
All these meta‑annotations reside in the org.springframework.boot.autoconfigure.condition package of the spring-boot-autoconfigure JAR.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Senior Brother's Insights
A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
