Java无预处理器,Spring通过@Profile、@ConditionalOnProperty及自定义@Conditional实现运行时条件化加载Bean,支持环境、配置项及复杂逻辑判断,本质是容器刷新阶段的动态注册。

Java 本身没有像 C/C++ 那样的预处理器,所以不存在真正的“条件编译”机制。但 Spring 提供了多种运行时条件化加载 Bean 的能力,能实现“不同环境下加载不同 Bean”的效果,这通常被开发者通俗地称为“条件编译注解”。核心是利用 Spring 的条件注解(@Conditional 及其衍生注解)配合环境配置(如 spring.profiles.active 或属性值)来控制 Bean 的注册。
用 @Profile 按环境激活 Bean
这是最常用、最直观的方式。通过定义 Profile(如 dev、test、prod),再用 @Profile 标记 Bean 类或配置类,Spring 启动时只注册匹配当前激活 Profile 的 Bean。
- 在
application.yml或启动参数中指定:spring.profiles.active=dev - 给 Bean 加注解:
@Component @Profile("dev")或@Configuration @Profile("prod") - 支持逻辑组合:
@Profile({"dev", "test"})表示任一匹配;@Profile("!prod")表示非 prod 环境
用 @ConditionalOnProperty 控制基于配置项的加载
当需要根据某个配置属性是否启用某功能时更灵活。例如开关数据库审计、启用缓存等。
- 写法示例:
@ConditionalOnProperty(name = "feature.cache.enabled", havingValue = "true") - 可在
application.yml中控制:feature.cache.enabled: true - 支持
matchIfMissing = true,即配置未定义时也满足条件(慎用)
用自定义 @Conditional 实现复杂判断逻辑
当内置条件不满足需求(比如要结合系统属性、JVM 版本、类路径是否存在某个类等),可实现 Condition 接口并配合 @Conditional 使用。
立即学习“Java免费学习笔记(深入)”;
- 编写一个类实现
org.springframework.context.annotation.Condition - 重写
matches()方法,在其中做任意 Java 判断(如System.getProperty("os.name").contains("Windows")) - 在 Bean 上标注:
@Conditional(MyOsCondition.class)
组合多个条件确保精确控制
单一条件有时不够严谨,Spring 支持组合使用。比如要求同时满足“是 dev 环境”且“配置项开启”才加载:
- 用
@Profile("dev")+@ConditionalOnProperty("debug.mode")—— 两者都需满足 - 或封装成一个复合
@Conditional,在matches()中调用多个条件判断 - 注意:Spring 默认是“与”逻辑(全部满足才注册),不支持直接写“或”,需在自定义 Condition 中实现
本质上这不是编译期行为,而是在容器刷新阶段由 Spring 解析并决策 Bean 是否注册。只要配置清晰、条件明确,就能达到和“条件编译”一样的效果,而且更灵活、可测试、易维护。


















