如何让Spring根据应用属性/环境变量跳过加载Configuration类?
Great question! Absolutely—Spring has built-in tools that let you conditionally instantiate beans based directly on application properties or environment variables, without relying solely on profiles. Here are the most practical approaches:
1. @ConditionalOnProperty (Simplest for Direct Property Checks)
This is the closest match to your pseudocode. It lets you specify a property key (and optional value) to control when a bean or configuration class is loaded.
Basic Example (Exact Property Match)
@Configuration @ConditionalOnProperty( name = "app.custom.config.enabled", havingValue = "true", matchIfMissing = false // Optional: defaults to false; bean won't load if property is missing ) public class MyCustomConfigurationClass { // Beans here only instantiate when app.custom.config.enabled=true }
Check for Property Presence (Any Value)
If you just need to confirm the property exists (regardless of its value), omit the havingValue parameter:
@ConditionalOnProperty(name = "app.custom.config.enabled")
Works with Environment Variables Too
Spring automatically maps environment variables to properties (e.g., APP_CUSTOM_CONFIG_ENABLED translates to app.custom.config.enabled). Set APP_CUSTOM_CONFIG_ENABLED=true in your environment, and the bean will load as expected.
2. @ConditionalOnExpression (For Complex Logic)
If you need to combine multiple properties or use more advanced conditions, use this annotation with Spring Expression Language (SpEL):
@Configuration @ConditionalOnExpression("${app.env} == 'dev' && ${app.debug.mode} == true") public class MyCustomConfigurationClass { // Loads only when both conditions are satisfied }
You can also reference environment variables directly in the expression:
@ConditionalOnExpression("#{environment.getProperty('APP_ENV') == 'dev'}")
3. Custom @Conditional Annotation (For Reusable Logic)
If you have a condition you'll use across multiple beans, create a custom annotation to keep your code clean:
First, define the annotation:
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Conditional(OnlyInstantiateWhenCondition.class) public @interface OnlyInstantiateWhen { String property(); String value() default "true"; }
Then implement the condition logic:
class OnlyInstantiateWhenCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Map<String, Object> attrs = metadata.getAnnotationAttributes(OnlyInstantiateWhen.class.getName()); String propertyKey = (String) attrs.get("property"); String expectedValue = (String) attrs.get("value"); String actualValue = context.getEnvironment().getProperty(propertyKey); return expectedValue.equals(actualValue); } }
Now you can use your custom annotation exactly like your pseudocode:
@Configuration @OnlyInstantiateWhen(property = "app.custom.config.enabled", value = "true") public class MyCustomConfigurationClass { // Beans load when the specified property matches the value }
Key Notes
- All these approaches work with properties from any Spring-supported source:
application.properties,application.yml, environment variables, system properties, etc. - Unlike
@Profile, these annotations let you fine-tune bean creation on a per-property basis, giving you more granular control than profile-based grouping.
内容的提问来源于stack exchange,提问作者soapergem

