一、引言在 Spring 框架的发展历程中注解驱动开发的出现彻底改变了传统 Spring 项目的配置模式 —— 从最初繁琐的 XML 配置到如今简洁高效的注解配置配置类已经成为现代 Spring Boot、Spring Cloud 项目中不可或缺的核心组成部分。对于每一位 Java 开发者而言熟练运用 Spring 配置类注解不仅能大幅提升开发效率让代码更简洁、更易维护更是深入理解 Spring 容器初始化、Bean 管理机制的关键。但在实际开发中很多同学往往只会简单使用Configuration和Bean注解对于ComponentScan、Import、Conditional、PropertySource等常用注解的用法、适用场景以及它们之间的区别和底层逻辑一知半解常常出现注解滥用、配置失效甚至排查半天找不到问题的情况。为了帮助大家系统掌握 Spring 配置类的常用注解彻底解决开发中的困惑本文将从配置类的核心作用出发逐一梳理 Spring 配置类中最常用、最实用、面试最高频的注解详细讲解每个注解的用法、参数含义、适用场景结合简单易懂的示例让大家既能快速上手使用也能理解其背后的原理真正做到 “知其然更知其所以然”助力大家写出规范、优雅、高效的 Spring 配置类。关于怎么样才算是配置类我已经在下面这篇博客中详细讲述大家可以去看一下Spring 核心机制到底什么样的类才算配置类Configuration 与 Component 的本质区别-CSDN博客二、ComponentScan2.1 定义ComponentScan标注在配置类上指定 Spring 扫描组件的包路径自动将路径下符合条件的类注册为 Bean无需手动用Bean定义。核心价值替代 XML 配置无需写context:component-scan base-packagexxx/用注解即可指定扫描范围自动注册 Bean扫描路径下的Component/Service/Controller等类自动纳入 Spring 容器管理灵活过滤支持包含 / 排除特定类精准控制哪些类被扫描、哪些不被扫描。2.2 参数参数名作用示例basePackages指定扫描的包路径字符串数组支持多个包【如果省略basePackagesComponentScan会默认扫描当前配置类所在的包及其所有子包】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注解 → 合并扫描范围。三、PropertySource3.1 作用PropertySource标注在配置类上加载指定路径的外部配置文件到 Spring 的 Environment 中使配置文件中的键值对可通过Value/ConfigurationProperties注入到代码中。核心价值配置解耦将数据库地址、端口、密钥等配置抽离到外部文件无需硬编码在代码中多环境适配不同环境使用不同配置文件如dev.properties/prod.properties只需切换加载的文件即可兼容传统配置支持加载.properties文件适配老项目的配置格式灵活扩展可加载多个配置文件配置项支持覆盖后加载的文件覆盖先加载的。3.2 参数参数名作用示例value指定配置文件路径字符串数组支持多个文件value {classpath:jdbc.properties, classpath:redis.properties}encoding配置文件编码解决中文乱码常用 UTF-8encoding UTF-8ignoreResourceNotFound是否忽略文件不存在的情况默认 false文件不存在会报错ignoreResourceNotFound truefactory自定义配置文件解析工厂用于加载.yml文件默认只支持.propertiesfactory YamlPropertySourceFactory.class3.3 注意Spring Boot 会自动加载classpath下的application.properties/application.yml无需手动加PropertySource如需加载自定义名称的配置文件如jdbc.properties/redis.yml才需要手动用PropertySourceSpring Boot 中可通过spring.config.name/spring.config.location配置加载的文件优先级高于PropertySource。3.4 优先级命令行参数如java -jar app.jar --jdbc.urlxxx系统环境变量PropertySource加载的自定义配置文件Spring Boot 自动加载的application.properties/application.ymlValue指定的默认值如Value(${key:默认值})。3.5 对比PropertySource负责加载配置文件ConfigurationProperties负责批量绑定配置值二者是 “加载 绑定” 的黄金组合关于ConfigurationProperties,Value可以看我的这篇博客Spring Boot 配置读取Value 与 ConfigurationProperties 怎么选-CSDN博客四、Conditional ConditionalOnXXX4.1 作用Conditional是 Spring 实现条件化配置的核心注解而ConditionalOnXXX是 Spring Boot 基于Conditional封装的一系列 “开箱即用” 的条件注解 —— 二者的核心作用都是根据指定条件决定配置类 / Bean 是否生效实现 “按需加载配置”是 Spring Boot 自动配置的底层核心。4.2 Conditional4.2.1 核心作用标注在配置类 /Bean方法上只有当自定义的Condition条件满足时配置类 / Bean 才会被 Spring 解析并生效。4.2.2 底层原理自定义类实现org.springframework.context.annotation.Condition接口重写matches()方法matches()返回true→ 条件满足配置生效返回false→ 配置不生效Spring 解析Conditional时会调用Condition的matches()方法判断条件。4.3 ConditionalOnXXXSpring 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时生效ConditionalOnWebApplicationConditionalOnNotWebApplication非 Web 应用时生效ConditionalOnNotWebApplication4.4 区别维度ConditionalSpring 原生ConditionalOnXXXSpring Boot 封装灵活性极高自定义 Condition支持任意逻辑中等封装好的固定条件开箱即用开发成本高需手写 Condition 实现类低直接用注解无需写额外代码适用场景自定义复杂条件如根据硬件、时间判断常规条件类存在、Bean 存在、配置匹配等底层关系父注解所有 ConditionalOnXXX 都基于它实现子注解封装了常用 Condition 逻辑五、Lazy5.1 作用Lazy可标注在配置类 /Bean方法 / 组件类 / 注入点上将 Bean 的初始化时机从「Spring 容器启动时」推迟到「首次使用时」核心解决 “启动慢、循环依赖、重量级 Bean 初始化” 问题。核心背景Spring 初始化规则Spring 中默认所有singleton单例Bean 都是饿汉式初始化容器启动时就创建所有单例 BeanprototypeBean 本身就是延迟初始化每次获取都新建Lazy对其无意义Lazy仅对单例 Bean生效是饿汉式初始化的 “开关”。5.2 用法标注在 Bean 方法上控制单个 Bean 延迟最常用的方式精准控制配置类中某个Bean的初始化时机标注在组件类上控制整个组件延迟直接标注在Component/Service/Controller等组件类上让整个组件延迟初始化标注在注入点上控制注入时延迟标注在Autowired/Inject注入点上仅对该注入点的 Bean 生效适合 “局部延迟”标注在 Configuration 类上全局延迟标注在配置类上会让该类中所有Bean方法定义的单例 Bean都默认延迟初始化批量控制优先级注解Lazy 全局配置六、Profile6.1 作用Profile是 Spring 实现多环境配置隔离的核心注解 —— 它的核心作用是根据指定的 “环境标识”如 dev/test/prod决定配置类 / Bean 仅在对应环境下生效实现 “一套代码适配多环境”无需手动修改配置。6.2 激活指定环境Profile可标注在配置类 /Bean方法上指定配置仅在「激活的环境匹配注解中的环境标识」时生效核心解决 “开发 / 测试 / 生产环境配置隔离” 问题。以下是激活的环境匹配注解中的环境标识代码context.getEnvironment().setActiveProfiles(prod)JVM 参数-Dspring.profiles.activeprodSpring Boot 配置文件spring.profiles.activeprod。6.3 优先级Profile在Bean 定义阶段生效容器启动时一旦环境不匹配Bean 不会被注册到容器中而非运行时动态切换。环境激活的优先级从高到低命令行参数-Dspring.profiles.active系统环境变量SPRING_PROFILES_ACTIVESpring Boot 配置文件application.yml中的spring.profiles.active代码手动设置context.getEnvironment().setActiveProfiles()。Profile 支持多环境激活后激活的环境中的同名 Bean 会覆盖先激活的6.4 与ConditionalProfile本质是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 仅在对应环境下生效实现一套代码适配多环境。
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博客二、ComponentScan2.1 定义ComponentScan标注在配置类上指定 Spring 扫描组件的包路径自动将路径下符合条件的类注册为 Bean无需手动用Bean定义。核心价值替代 XML 配置无需写context:component-scan base-packagexxx/用注解即可指定扫描范围自动注册 Bean扫描路径下的Component/Service/Controller等类自动纳入 Spring 容器管理灵活过滤支持包含 / 排除特定类精准控制哪些类被扫描、哪些不被扫描。2.2 参数参数名作用示例basePackages指定扫描的包路径字符串数组支持多个包【如果省略basePackagesComponentScan会默认扫描当前配置类所在的包及其所有子包】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注解 → 合并扫描范围。三、PropertySource3.1 作用PropertySource标注在配置类上加载指定路径的外部配置文件到 Spring 的 Environment 中使配置文件中的键值对可通过Value/ConfigurationProperties注入到代码中。核心价值配置解耦将数据库地址、端口、密钥等配置抽离到外部文件无需硬编码在代码中多环境适配不同环境使用不同配置文件如dev.properties/prod.properties只需切换加载的文件即可兼容传统配置支持加载.properties文件适配老项目的配置格式灵活扩展可加载多个配置文件配置项支持覆盖后加载的文件覆盖先加载的。3.2 参数参数名作用示例value指定配置文件路径字符串数组支持多个文件value {classpath:jdbc.properties, classpath:redis.properties}encoding配置文件编码解决中文乱码常用 UTF-8encoding UTF-8ignoreResourceNotFound是否忽略文件不存在的情况默认 false文件不存在会报错ignoreResourceNotFound truefactory自定义配置文件解析工厂用于加载.yml文件默认只支持.propertiesfactory YamlPropertySourceFactory.class3.3 注意Spring Boot 会自动加载classpath下的application.properties/application.yml无需手动加PropertySource如需加载自定义名称的配置文件如jdbc.properties/redis.yml才需要手动用PropertySourceSpring Boot 中可通过spring.config.name/spring.config.location配置加载的文件优先级高于PropertySource。3.4 优先级命令行参数如java -jar app.jar --jdbc.urlxxx系统环境变量PropertySource加载的自定义配置文件Spring Boot 自动加载的application.properties/application.ymlValue指定的默认值如Value(${key:默认值})。3.5 对比PropertySource负责加载配置文件ConfigurationProperties负责批量绑定配置值二者是 “加载 绑定” 的黄金组合关于ConfigurationProperties,Value可以看我的这篇博客Spring Boot 配置读取Value 与 ConfigurationProperties 怎么选-CSDN博客四、Conditional ConditionalOnXXX4.1 作用Conditional是 Spring 实现条件化配置的核心注解而ConditionalOnXXX是 Spring Boot 基于Conditional封装的一系列 “开箱即用” 的条件注解 —— 二者的核心作用都是根据指定条件决定配置类 / Bean 是否生效实现 “按需加载配置”是 Spring Boot 自动配置的底层核心。4.2 Conditional4.2.1 核心作用标注在配置类 /Bean方法上只有当自定义的Condition条件满足时配置类 / Bean 才会被 Spring 解析并生效。4.2.2 底层原理自定义类实现org.springframework.context.annotation.Condition接口重写matches()方法matches()返回true→ 条件满足配置生效返回false→ 配置不生效Spring 解析Conditional时会调用Condition的matches()方法判断条件。4.3 ConditionalOnXXXSpring 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时生效ConditionalOnWebApplicationConditionalOnNotWebApplication非 Web 应用时生效ConditionalOnNotWebApplication4.4 区别维度ConditionalSpring 原生ConditionalOnXXXSpring Boot 封装灵活性极高自定义 Condition支持任意逻辑中等封装好的固定条件开箱即用开发成本高需手写 Condition 实现类低直接用注解无需写额外代码适用场景自定义复杂条件如根据硬件、时间判断常规条件类存在、Bean 存在、配置匹配等底层关系父注解所有 ConditionalOnXXX 都基于它实现子注解封装了常用 Condition 逻辑五、Lazy5.1 作用Lazy可标注在配置类 /Bean方法 / 组件类 / 注入点上将 Bean 的初始化时机从「Spring 容器启动时」推迟到「首次使用时」核心解决 “启动慢、循环依赖、重量级 Bean 初始化” 问题。核心背景Spring 初始化规则Spring 中默认所有singleton单例Bean 都是饿汉式初始化容器启动时就创建所有单例 BeanprototypeBean 本身就是延迟初始化每次获取都新建Lazy对其无意义Lazy仅对单例 Bean生效是饿汉式初始化的 “开关”。5.2 用法标注在 Bean 方法上控制单个 Bean 延迟最常用的方式精准控制配置类中某个Bean的初始化时机标注在组件类上控制整个组件延迟直接标注在Component/Service/Controller等组件类上让整个组件延迟初始化标注在注入点上控制注入时延迟标注在Autowired/Inject注入点上仅对该注入点的 Bean 生效适合 “局部延迟”标注在 Configuration 类上全局延迟标注在配置类上会让该类中所有Bean方法定义的单例 Bean都默认延迟初始化批量控制优先级注解Lazy 全局配置六、Profile6.1 作用Profile是 Spring 实现多环境配置隔离的核心注解 —— 它的核心作用是根据指定的 “环境标识”如 dev/test/prod决定配置类 / Bean 仅在对应环境下生效实现 “一套代码适配多环境”无需手动修改配置。6.2 激活指定环境Profile可标注在配置类 /Bean方法上指定配置仅在「激活的环境匹配注解中的环境标识」时生效核心解决 “开发 / 测试 / 生产环境配置隔离” 问题。以下是激活的环境匹配注解中的环境标识代码context.getEnvironment().setActiveProfiles(prod)JVM 参数-Dspring.profiles.activeprodSpring Boot 配置文件spring.profiles.activeprod。6.3 优先级Profile在Bean 定义阶段生效容器启动时一旦环境不匹配Bean 不会被注册到容器中而非运行时动态切换。环境激活的优先级从高到低命令行参数-Dspring.profiles.active系统环境变量SPRING_PROFILES_ACTIVESpring Boot 配置文件application.yml中的spring.profiles.active代码手动设置context.getEnvironment().setActiveProfiles()。Profile 支持多环境激活后激活的环境中的同名 Bean 会覆盖先激活的6.4 与ConditionalProfile本质是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 仅在对应环境下生效实现一套代码适配多环境。