SoFunction
Updated on 2025-03-04

Spring Boot @Conditional annotation usage examples

In Spring Boot,@ConditionalAnnotations are used to conditionally register beans. This means it can decide whether a specific bean should be created based on certain conditions. This annotation can be placed on a configuration class or method, and it will determine whether the corresponding component should be instantiated based on the provided set of conditions.

To use@ConditionalWhen annotating, it needs to be implementedConditionInterface and rewritematchesmethod. This method returns a Boolean value to indicate whether the condition matches. If the condition is true, create a bean; otherwise, create the bean is skipped.

Here is a simple example showing how to use custom conditions:

import ;
import ;
import ;
public class MyCustomCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // Add your conditional logic here        // For example, check system properties, environment variables, existing beans, etc.        return false; // Return true or false according to conditional logic    }
}
  • ConditionContext: Provides access to the current parsing context, including:
    • Environment: It can be used to obtain environment variables, system properties, etc.
    • BeanFactory: If available, you can access the registered beans through it.
    • ClassLoader: can be used to check whether the class on the classpath exists.
    • EvaluationContext: Can be used to evaluate SpEL expressions.
  • AnnotatedTypeMetadata provides access to methods or class metadata with annotated, such as annotated property values.

Custom condition class

Suppose we have an application that should decide whether to load a specific bean based on the operating system. We can create a name calledOnWindowsConditionConditional class:

import ;
import ;
import ;
public class OnWindowsCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return "win".equals(().getProperty("").toLowerCase().substring(0, 3));
    }
}

Then use it in the configuration class:

@Configuration
public class MyConfig {
    @Bean
    @Conditional()
    public WindowsSpecificService windowsSpecificService() {
        return new WindowsSpecificServiceImpl();
    }
}

Spring Boot provides built-in conditional annotations

@ConditionalOnProperty

When you want to create a bean based on whether the attributes in the configuration file exist or have a specific value, you can use@ConditionalOnPropertyannotation. For example:

@Configuration
public class MyConfig {
    @Bean
    @ConditionalOnProperty(name = "", havingValue = "true")
    public MyFeature myFeature() {
        return new MyFeature();
    }
}

In this example, only if the configuration file has a name calledThe attribute and its value istrueOnly whenMyFeature bean。

More usages

  • prefix: Specify the attribute name prefix.
  • name: Specify the attribute name (can be an array, representing multiple attributes).
  • havingValue: Specifies the value that the property must have, the default is an empty string.
  • matchIfMissing: If no attribute is found, the default match or not is:false

For example, you can configure it like this:

@Bean
@ConditionalOnProperty(prefix = "app", name = "", havingValue = "true", matchIfMissing = false)
public FeatureService featureService() {
    return new FeatureServiceImpl();
}

This will ensure that only in=trueIt will be created only whenFeatureServicebean; if the property is not set andmatchIfMissing=false, it will not be created.

@ConditionalOnClass and @ConditionalOnMissingClass

These two annotations are used to check whether certain classes exist or do not exist under the classpath. This is very useful when integrating third-party libraries, because you can conditionally register beans related to these libraries. For example:

@Configuration
@ConditionalOnClass(name = "")
public class ExternalLibraryConfig {
    // ...
}

If there is a classpathExternalLibraryClassclass, this configuration will be applied.

@ConditionalOnBean and @ConditionalOnMissingBean

These annotations are used to decide whether to create a new bean based on whether there is a bean of the specified type in the context. This is very useful for ensuring that beans with the same functionality are not registered repeatedly.

@Bean
@ConditionalOnMissingBean()
public MyService myService() {
    return new MyServiceImpl();
}

What this means here is: if there is no type in the context yetMyServicea new bean is createdMyServiceImplInstance and register as bean.

@ConditionalOnExpression using SpEL expression

Can be passed@ConditionalOnExpressionTo write complex conditional expressions. For example, it is determined whether to create a bean based on multiple attribute combinations or environment variables.

@Bean
@ConditionalOnExpression("${:'default'} == 'myapp' && ${env:dev} == 'prod'")
public ProdSpecificBean prodSpecificBean() {
    return new ProdSpecificBean();
}

This code means only if the application name is'myapp'And environment variablesenvSet as'prod'Only whenProdSpecificBean

Use scenarios

Dynamic condition evaluation

Sometimes you may need to dynamically adjust the bean's behavior after the application is started based on certain changes (such as user input or the status of external services). Although@ConditionalIt is mainly used for static condition judgment at startup, but you can achieve similar effects by combining other mechanisms (such as event listeners, timing tasks, etc.).

@Configuration
public class DynamicConditionConfig {
    private final AtomicBoolean shouldCreateBean = new AtomicBoolean(false);
    @Bean
    @ConditionalOnProperty(name = "", havingValue = "true")
    public MyDynamicBean myDynamicBean() {
        return () -> ();
    }
    // Methods to simulate external trigger update condition status    public void updateCondition(boolean value) {
        (value);
    }
}

In this example,MyDynamicBeanThe behavior depends on an atomic boolean variableshouldCreateBean, This variable can be changed at runtime, affecting the bean's behavior.

Conditioned AOP section

You can also apply conditions to AOP sections for more flexible cross-cutting concern management. For example:

@Aspect
@ConditionalOnProperty(name = "", havingValue = "true")
public class LoggingAspect {
    @Around("execution(* .*.*(..))")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = ();
        Object proceed = ();
        long executionTime = () - start;
        (().getClass().getName() + "." + ().getName() + " executed in " + executionTime + "ms");
        return proceed;
    }
}

This code means only=trueLogging facets will only be activated.

use@Profileand@ConditionalCombined

Sometimes, you may want to combine@Profileand@Conditionalto create more granular conditional logic. For example:

@Configuration
@Profile("dev")
public class DevConfig {
    @Bean
    @ConditionalOnProperty(name = "", havingValue = "true")
    public FeatureX featureX() {
        return new FeatureXImpl();
    }
}

What this means here is: only in the development environment (devProfile) and=trueCreated only whenFeatureX bean。

Conditional agent

For beans that require delayed initialization or lazy loading, you can consider using@Scope("proxy")and@LazyCombined with comments@Conditionalto implement conditional proxy.

@Bean
@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
@Lazy
@ConditionalOnProperty(name = "", havingValue = "true")
public LazyInitFeature lazyInitFeature() {
    return new LazyInitFeatureImpl();
}

This ensures that only when the conditions are met and the first visit islazyInitFeatureIt will be instantiated only when it is bean.

Debugging Tips

use@PostConstructand@PreDestroyMonitor the bean life cycle

To better understand which beans are created or destroyed, you can add them in the bean class@PostConstructand@PreDestroymethod and output log information.

@Component
@ConditionalOnProperty(name = "", havingValue = "true")
public class FeatureY {
    @PostConstruct
    public void init() {
        ("FeatureY initialized.");
    }
    @PreDestroy
    public void destroy() {
        ("FeatureY destroyed.");
    }
}

This approach helps track the life cycle of the bean and confirms that the conditions work as expected.

use-mode=offReduce interference

When you focus on debugging conditional logic, closing Spring Boot boot banners can help reduce unnecessary output and make logs clearer.

-mode=off

Frequently Asked Questions

Environment properties are not loading correctly

If you find that the conditional annotation does not work as expected, please check whether the environment properties file is loaded correctly (e.g.or). Make sure these files are in the correct path and contain the required property definitions.

Classpath conflict

Classpath conflict is a common cause when encountering the problem that conditional annotations do not work. Especially when you use@ConditionalOnClassor@ConditionalOnMissingClassWhen , make sure there are no duplicate dependencies in the project. You can use Maven or Gradle commands to analyze dependency trees:

Maven:

mvn dependency:tree

Gradle:

gradle dependencies

Conditional logic error

Carefully review your conditional logic to make sure they meet expectations. The behavior of each condition can be verified by unit testing. For example:

@Test
void testFeatureYEnabled() {
    ApplicationContextRunner runner = new ApplicationContextRunner()
        .withPropertyValues("=true");
    (context -> assertThat(context).hasSingleBean());
}
@Test
void testFeatureYDisabled() {
    ApplicationContextRunner runner = new ApplicationContextRunner()
        .withPropertyValues("=false");
    (context -> assertThat(context).doesNotHaveBean());
}

Things to note

  • Conditional annotations are only applicable to Spring's configuration phase, so they cannot be used for runtime decisions.
  • When used@ConditionalWhen annotating other conditionals, please make sure that your conditional logic does not cause circular dependencies or unexpected behavior.
  • When writing conditional logic, considering the performance impact, try to make conditional judgments lightweight.

This is all about this article about Spring Boot @Conditional annotations. For more related Spring Boot @Conditional annotations, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!