欢迎光临
我们一直在努力

Spring 配置类常用注解,一篇就够了

一、引言

在 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 定义。

核心价值

  • 替代 XML 配置:无需写 <context:component-scan base-package="xxx"/>,用注解即可指定扫描范围;
  • 自动注册 Bean:扫描路径下的 @Component/@Service/@Controller 等类,自动纳入 Spring 容器管理;
  • 灵活过滤:支持包含 / 排除特定类,精准控制哪些类被扫描、哪些不被扫描。
  • 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 注入到代码中。

    核心价值

  • 配置解耦:将数据库地址、端口、密钥等配置抽离到外部文件,无需硬编码在代码中;
  • 多环境适配:不同环境使用不同配置文件(如 dev.properties/prod.properties),只需切换加载的文件即可;
  • 兼容传统配置:支持加载 .properties 文件,适配老项目的配置格式;
  • 灵活扩展:可加载多个配置文件,配置项支持覆盖(后加载的文件覆盖先加载的)。
  • 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 区别

    维度@Conditional(Spring 原生)@ConditionalOnXXX(Spring Boot 封装)
    灵活性 极高(自定义 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 不会被注册到容器中,而非运行时动态切换。

    环境激活的优先级从高到低:

  • 命令行参数(-Dspring.profiles.active);
  • 系统环境变量(SPRING_PROFILES_ACTIVE);
  • Spring Boot 配置文件(application.yml 中的 spring.profiles.active);
  • 代码手动设置(context.getEnvironment().setActiveProfiles())。
  • @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 仅在对应环境下生效,实现一套代码适配多环境。

    赞(0)
    未经允许不得转载:171主机测评 » Spring 配置类常用注解,一篇就够了
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址