一、引言
在 Spring 框架的发展历程中,注解驱动开发的出现,彻底改变了传统 Spring 项目的配置模式 —— 从最初繁琐的 XML 配置,到如今简洁高效的注解配置,配置类已经成为现代 Spring Boot、Spring Cloud 项目中不可或缺的核心组成部分。
对于每一位 Java 开发者而言,熟练运用 Spring 配置类注解,不仅能大幅提升开发效率,让代码更简洁、更易维护,更是深入理解 Spring 容器初始化、Bean 管理机制的关键。但在实际开发中,很多同学往往只会简单使用 @Configuration 和 @Bean 注解,对于 @ComponentScan、@Import、@Conditional、@PropertySource 等常用注解的用法、适用场景,以及它们之间的区别和底层逻辑一知半解,常常出现注解滥用、配置失效,甚至排查半天找不到问题的情况。
为了帮助大家系统掌握 Spring 配置类的常用注解,彻底解决开发中的困惑,本文将从配置类的核心作用出发,逐一梳理 Spring 配置类中最常用、最实用、面试最高频的注解,详细讲解每个注解的用法、参数含义、适用场景,结合简单易懂的示例,让大家既能快速上手使用,也能理解其背后的原理,真正做到 “知其然,更知其所以然”,助力大家写出规范、优雅、高效的 Spring 配置类。
关于怎么样才算是配置类,我已经在下面这篇博客中详细讲述,大家可以去看一下
Spring 核心机制:到底什么样的类才算配置类?@Configuration 与 @Component 的本质区别-CSDN博客
二、@ComponentScan
2.1 定义
@ComponentScan 标注在配置类上,指定 Spring 扫描组件的包路径,自动将路径下符合条件的类注册为 Bean,无需手动用 @Bean 定义。
核心价值
2.2 参数
| basePackages | 指定扫描的包路径(字符串数组,支持多个包)【如果省略 basePackages,@ComponentScan 会默认扫描当前配置类所在的包及其所有子包】 | basePackages = {"com.example.service", "com.example.controller"} |
| basePackageClasses | 指定扫描的基准类(类所在包及子包被扫描,类型安全,推荐) | basePackageClasses = {UserService.class, OrderController.class} |
| includeFilters | 只扫描符合条件的类(白名单) | 只扫描带 @Controller 注解的类 |
| excludeFilters | 排除不需要扫描的类(黑名单) | 排除带 @Service 注解的类 |
| useDefaultFilters | 是否启用默认过滤器(默认 true,扫描 @Component 及其衍生注解) | useDefaultFilters = false(仅扫描 includeFilters 指定的类) |
2.3 优先级
Spring Boot 的核心注解 @SpringBootApplication 已经内置了 @ComponentScan,默认扫描启动类所在的包及其子包—— 因此 Spring Boot 项目中,无需手动加 @ComponentScan,除非需要扫描启动类包外的组件
扫描规则的优先级
- 显式指定 basePackages/basePackageClasses → 优先扫描指定包;
- 未指定 → 扫描当前配置类所在包;
- 多个 @ComponentScan 注解 → 合并扫描范围。
三、@PropertySource
3.1 作用
@PropertySource 标注在配置类上,加载指定路径的外部配置文件到 Spring 的 Environment 中,使配置文件中的键值对可通过 @Value/@ConfigurationProperties 注入到代码中。
核心价值
3.2 参数
| value | 指定配置文件路径(字符串数组,支持多个文件) | value = {"classpath:jdbc.properties", "classpath:redis.properties"} |
| encoding | 配置文件编码(解决中文乱码,常用 UTF-8) | encoding = "UTF-8" |
| ignoreResourceNotFound | 是否忽略文件不存在的情况(默认 false,文件不存在会报错) | ignoreResourceNotFound = true |
| factory | 自定义配置文件解析工厂(用于加载 .yml 文件,默认只支持 .properties) | factory = YamlPropertySourceFactory.class |
3.3 注意
- Spring Boot 会自动加载 classpath 下的 application.properties/application.yml,无需手动加 @PropertySource;
- 如需加载自定义名称的配置文件(如 jdbc.properties/redis.yml),才需要手动用 @PropertySource;
- Spring Boot 中可通过 spring.config.name/spring.config.location 配置加载的文件,优先级高于 @PropertySource。
3.4 优先级
- 命令行参数(如 java -jar app.jar –jdbc.url=xxx);
- 系统环境变量;
- @PropertySource 加载的自定义配置文件;
- Spring Boot 自动加载的 application.properties/application.yml;
- @Value 指定的默认值(如 @Value("${key:默认值}"))。
3.5 对比
@PropertySource 负责加载配置文件,@ConfigurationProperties 负责批量绑定配置值,二者是 “加载 + 绑定” 的黄金组合
关于@ConfigurationProperties,@Value可以看我的这篇博客
Spring Boot 配置读取:@Value 与 @ConfigurationProperties 怎么选?-CSDN博客
四、@Conditional & @ConditionalOnXXX
4.1 作用
@Conditional 是 Spring 实现条件化配置的核心注解,而 @ConditionalOnXXX 是 Spring Boot 基于 @Conditional 封装的一系列 “开箱即用” 的条件注解 —— 二者的核心作用都是:根据指定条件决定配置类 / Bean 是否生效,实现 “按需加载配置”,是 Spring Boot 自动配置的底层核心。
4.2 @Conditional
4.2.1 核心作用
标注在配置类 /@Bean 方法上,只有当自定义的 Condition 条件满足时,配置类 / Bean 才会被 Spring 解析并生效。
4.2.2 底层原理
- 自定义类实现 org.springframework.context.annotation.Condition 接口,重写 matches() 方法;
- matches() 返回 true → 条件满足,配置生效;返回 false → 配置不生效;
- Spring 解析 @Conditional 时,会调用 Condition 的 matches() 方法判断条件。
4.3 @ConditionalOnXXX
Spring Boot 为了简化条件配置,基于 @Conditional 封装了一系列高频使用的条件注解(前缀为 @ConditionalOn),无需自定义 Condition,直接开箱即用。
| 类 / 依赖相关 | @ConditionalOnClass | 类路径下存在指定类时生效 | @ConditionalOnClass(RedisTemplate.class) |
| @ConditionalOnMissingClass | 类路径下不存在指定类时生效 | @ConditionalOnMissingClass("org.springframework.data.redis.core.RedisTemplate") | |
| Bean 相关 | @ConditionalOnBean | 容器中存在指定 Bean 时生效 | @ConditionalOnBean(DataSource.class) |
| @ConditionalOnMissingBean | 容器中不存在指定 Bean 时生效(避免重复定义) | @ConditionalOnMissingBean(RedisTemplate.class) | |
| 配置属性相关 | @ConditionalOnProperty | 配置文件中存在指定属性且值匹配时生效 | @ConditionalOnProperty(prefix = "redis", name = "enabled", havingValue = "true") |
| 环境相关 | @ConditionalOnEnvironment | 指定环境(dev/test/prod)时生效 | @ConditionalOnEnvironment(value = "prod") |
| 资源相关 | @ConditionalOnResource | 存在指定资源(文件)时生效 | @ConditionalOnResource(resources = "classpath:jdbc.properties") |
| Web 环境相关 | @ConditionalOnWebApplication | 是 Web 应用(Servlet/Reactive)时生效 | @ConditionalOnWebApplication |
| @ConditionalOnNotWebApplication | 非 Web 应用时生效 | @ConditionalOnNotWebApplication |
4.4 区别
| 灵活性 | 极高(自定义 Condition,支持任意逻辑) | 中等(封装好的固定条件,开箱即用) |
| 开发成本 | 高(需手写 Condition 实现类) | 低(直接用注解,无需写额外代码) |
| 适用场景 | 自定义复杂条件(如根据硬件、时间判断) | 常规条件(类存在、Bean 存在、配置匹配等) |
| 底层关系 | 父注解,所有 @ConditionalOnXXX 都基于它实现 | 子注解,封装了常用 Condition 逻辑 |
五、@Lazy
5.1 作用
@Lazy 可标注在配置类 /@Bean 方法 / 组件类 / 注入点上,将 Bean 的初始化时机从「Spring 容器启动时」推迟到「首次使用时」,核心解决 “启动慢、循环依赖、重量级 Bean 初始化” 问题。
核心背景:Spring 初始化规则
- Spring 中默认所有 singleton(单例)Bean 都是 饿汉式初始化:容器启动时就创建所有单例 Bean;
- prototypeBean 本身就是延迟初始化(每次获取都新建),@Lazy 对其无意义;
- @Lazy 仅对 单例 Bean 生效,是饿汉式初始化的 “开关”。
5.2 用法
标注在 @Bean 方法上(控制单个 Bean 延迟)
- 最常用的方式,精准控制配置类中某个 @Bean 的初始化时机
标注在组件类上(控制整个组件延迟)
- 直接标注在 @Component/@Service/@Controller 等组件类上,让整个组件延迟初始化
标注在注入点上(控制注入时延迟)
- 标注在 @Autowired/@Inject 注入点上,仅对该注入点的 Bean 生效(适合 “局部延迟”)
标注在 @Configuration 类上(全局延迟)
- 标注在配置类上,会让该类中所有 @Bean 方法定义的单例 Bean 都默认延迟初始化(批量控制)
优先级:注解 @Lazy > 全局配置
六、@Profile
6.1 作用
@Profile 是 Spring 实现多环境配置隔离的核心注解 —— 它的核心作用是:根据指定的 “环境标识”(如 dev/test/prod),决定配置类 / Bean 仅在对应环境下生效,实现 “一套代码适配多环境”,无需手动修改配置。
6.2 激活指定环境
@Profile 可标注在配置类 /@Bean 方法上,指定配置仅在「激活的环境匹配注解中的环境标识」时生效,核心解决 “开发 / 测试 / 生产环境配置隔离” 问题。
以下是激活的环境匹配注解中的环境标识:
- 代码:context.getEnvironment().setActiveProfiles("prod");
- JVM 参数:-Dspring.profiles.active=prod;
- Spring Boot 配置文件:spring.profiles.active=prod。
6.3 优先级
@Profile 在 Bean 定义阶段生效(容器启动时),一旦环境不匹配,Bean 不会被注册到容器中,而非运行时动态切换。
环境激活的优先级从高到低:
@Profile 支持多环境激活,后激活的环境中的同名 Bean 会覆盖先激活的
6.4 与@Conditional
@Profile 本质是 @Conditional 的特殊实现(底层是 ProfileCondition),二者可叠加使用
七、总结
| @ComponentScan | 组件扫描器 | 指定 Spring 扫描组件的包路径,自动将 @Component/@Service/@Controller 等类注册为 Bean,替代 XML 的 <context:component-scan>。 |
| @PropertySource | 配置文件加载器 | 加载外部 .properties/.yml 配置文件到 Spring 环境,配合 @Value/@ConfigurationProperties 读取配置,实现配置与代码解耦。 |
| @Conditional & @ConditionalOnXXX | 条件化配置开关 | 根据自定义条件(@Conditional)或预设条件(@ConditionalOnClass/@ConditionalOnMissingBean/@ConditionalOnProperty 等),决定配置类 / Bean 是否生效,是 Spring Boot 自动配置的底层核心。 |
| @Lazy | 延迟初始化开关 | 控制单例 Bean 的初始化时机,从「容器启动时」推迟到「首次使用时」,优化启动速度、解决循环依赖、处理重量级 Bean 初始化。 |
| @Profile | 多环境隔离开关 | 根据激活的环境标识(如 dev/test/prod),让配置类 / Bean 仅在对应环境下生效,实现一套代码适配多环境。 |

