Spring Boot 配置类注解@Configuration详解:从基础到实战
在 Spring Boot 开发中,配置类是替代传统 XML 配置的核心载体,通过一系列注解可实现 Bean 注册、属性绑定、条件装配等关键功能。本文将深入解析常用配置类注解,结合示例代码与实战场景,帮你彻底掌握配置类的使用技巧。
一、核心基础注解:构建配置类基石
1. @Configuration:标记配置类
作用
声明当前类为配置类,相当于传统 Spring 的applicationContext.xml
文件,Spring 容器会自动扫描并加载该类中的配置。
用法与示例
import org.springframework.context.annotation.Configuration;// 标记当前类为配置类@Configurationpublic class AppConfig {// 配置内容(如@Bean注解定义Bean)}
关键注意点
+ **proxyBeanMethods 属性**:Spring Boot 2.x 新增,默认值为`true`。// 无Bean依赖场景,设置proxyBeanMethods=false优化性能@Configuration(proxyBeanMethods = false)public class SimpleConfig {@Beanpublic User user() {return new User();}}
true
(默认):配置类会被动态代理,类中 @Bean 方法调用时会返回容器中已存在的 Bean 实例(保证单例)。false
:配置类不会生成代理,@Bean 方法调用时会创建新实例,适用于无依赖的简单配置,可提升启动性能。示例:- 与
@Component
的区别:@Configuration
本质是@Component
的子类,但前者更强调 “配置功能”,且支持 proxyBeanMethods 特性。
2. @Bean:注册 Bean 实例
作用
在配置类中定义方法,方法返回值会被注册为 Spring 容器中的 Bean,默认 Bean 名称为方法名。用法与示例
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class BeanConfig {// 注册名为"userService"的Bean,类型为UserService@Beanpublic UserService userService() {return new UserService();}// 自定义Bean名称,同时指定初始化和销毁方法@Bean(name = "orderService", // 自定义Bean名称initMethod = "init", // 初始化方法(对应OrderService的init())destroyMethod = "destroy" // 销毁方法(对应OrderService的destroy()))public OrderService createOrderService() {return new OrderService();}}// 对应Bean类class OrderService {public void init() {System.out.println("OrderService初始化");}public void destroy() {System.out.println("OrderService销毁");}}
关键注意点
+ Bean 的作用域:默认是单例(`singleton`),可通过`@Scope`注解修改(如`@Scope("prototype")`多例)。 + 依赖注入:@Bean 方法可通过参数注入容器中已存在的 Bean,示例:
@Beanpublic OrderService orderService(UserService userService) {// 注入UserService依赖OrderService orderService = new OrderService();orderService.setUserService(userService);return orderService;}
二、依赖导入注解:组合多配置资源
1. @Import:直接导入配置类 / Bean
作用
在一个配置类中导入其他配置类、普通类或特定接口实现类,无需被导入类标注`@Configuration`。用法与示例
(1)导入配置类
// 配置类1@Configurationpublic class DbConfig {@Beanpublic DataSource dataSource() {return new HikariDataSource();}}// 配置类2:导入DbConfig,无需再扫描DbConfig@Configuration@Import(DbConfig.class)public class AppMainConfig {// 可直接使用DbConfig中注册的DataSource}
(2)导入普通类(自动注册为 Bean)
// 普通类(无任何注解)public class LogService {public void log() {System.out.println("日志输出");}}// 配置类导入普通类,LogService会被注册为Bean@Configuration@Import(LogService.class)public class AppConfig {}
(3)导入 ImportSelector 实现类(动态导入)
// 自定义ImportSelector,指定要导入的类public class MyImportSelector implements ImportSelector {@Overridepublic String\[] selectImports(AnnotationMetadata importingClassMetadata) {// 返回要导入的类的全限定名数组return new String\[]{"com.example.service.CacheService"};}}// 配置类导入Selector@Configuration@Import(MyImportSelector.class)public class AppConfig {}
2. @ImportResource:导入 XML 配置
作用
兼容传统 Spring XML 配置文件,将 XML 中定义的 Bean 导入到 Spring Boot 容器中。用法与示例
// 导入classpath下的spring-bean.xml配置@Configuration@ImportResource("classpath:spring-bean.xml")public class XmlConfig {}// spring-bean.xml示例\<?xml version="1.0" encoding="UTF-8"?>\<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">\<bean id="xmlService" class="com.example.service.XmlService"/>\</beans>
三、属性绑定注解:关联配置文件
1. @ConfigurationProperties:批量绑定属性
作用
将配置文件(如 application.yml/application.properties)中的属性批量绑定到 Java 类的字段上,替代繁琐的@Value
注解。
用法与示例
(1)定义属性绑定类
import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;// 前缀prefix指定配置文件中属性的统一前缀@ConfigurationProperties(prefix = "app.datasource")@Component // 注册为Bean,或通过@EnableConfigurationProperties启用public class DataSourceProperties {private String url;private String username;private String password;private int maxPoolSize;// 必须提供getter和setter方法public String getUrl() { return url; }public void setUrl(String url) { this.url = url; }// 其他字段的getter/setter省略}
(2)配置文件(application.yml)
app:datasource:url: jdbc:mysql://localhost:3306/testusername: rootpassword: 123456max-pool-size: 10 # 支持"-"分隔符,自动映射到maxPoolSize
(3)启用属性绑定(两种方式)
+ 方式一:在绑定类上添加`@Component`(如上例)。 + 方式二:在配置类上添加`@EnableConfigurationProperties`:@Configuration@EnableConfigurationProperties(DataSourceProperties.class)public class DataSourceConfig {// 可注入DataSourceProperties使用@Beanpublic DataSource dataSource(DataSourceProperties properties) {HikariDataSource dataSource = new HikariDataSource();dataSource.setJdbcUrl(properties.getUrl());dataSource.setUsername(properties.getUsername());dataSource.setPassword(properties.getPassword());dataSource.setMaximumPoolSize(properties.getMaxPoolSize());return dataSource;}}
关键注意点
+ 支持松散绑定:配置文件中的`max-pool-size`可映射到 Java 类的`maxPoolSize`(驼峰命名)。 + 支持 JSR303 校验:添加`@Validated`注解实现属性校验,示例:import org.springframework.validation.annotation.Validated;import javax.validation.constraints.NotEmpty;import javax.validation.constraints.Max;@ConfigurationProperties(prefix = "app.datasource")@Component@Validated // 启用校验public class DataSourceProperties {@NotEmpty(message = "数据库URL不能为空")private String url;@Max(value = 20, message = "最大连接池不能超过20")private int maxPoolSize;// 省略getter/setter}
2. @PropertySource:加载自定义配置文件
作用
加载类路径下的自定义配置文件(非默认的 application.yml/properties),配合@Value
或@ConfigurationProperties
使用。
用法与示例
import org.springframework.context.annotation.PropertySource;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;// 加载classpath下的custom.properties文件@Component@PropertySource("classpath:custom.properties")@ConfigurationProperties(prefix = "custom")public class CustomProperties {private String name;private String version;// getter/setter省略}// custom.properties文件custom.name=MyAppcustom.version=1.0.0
关键注意点
- 默认只支持 properties 格式文件,加载 yaml 文件需指定
factory
:
@PropertySource(value = "classpath:custom.yml", factory = YamlPropertySourceFactory.class)
(需自定义YamlPropertySourceFactory
,或引入 Spring Boot 扩展依赖)
四、条件装配注解:按需注册 Bean
条件注解用于根据特定条件决定 Bean 是否注册到容器中,核心是@Conditional
接口,Spring Boot 提供了多种开箱即用的实现。
1. 常用条件注解
注解 | 作用 | 示例 |
---|---|---|
@ConditionalOnClass | 当类路径存在指定类时生效 | @ConditionalOnClass(DataSource.class) |
@ConditionalOnMissingClass | 当类路径不存在指定类时生效 | @ConditionalOnMissingClass("com.example.service.CacheService") |
@ConditionalOnBean | 当容器中存在指定 Bean 时生效 | @ConditionalOnBean(DataSource.class) |
@ConditionalOnMissingBean | 当容器中不存在指定 Bean 时生效 | @ConditionalOnMissingBean(UserService.class) |
@ConditionalOnProperty | 当配置文件中指定属性满足条件时生效 | @ConditionalOnProperty(prefix = "app", name = "enable", havingValue = "true") |
@ConditionalOnWebApplication | 当应用是 Web 应用时生效 | 直接标注在配置类或 @Bean 方法上 |
@ConditionalOnNotWebApplication | 当应用不是 Web 应用时生效 | 直接标注在配置类或 @Bean 方法上 |
2. 用法示例
@Configurationpublic class ConditionalConfig {// 当配置文件中app.enable-cache=true时,注册CacheService@Bean@ConditionalOnProperty(prefix = "app", name = "enable-cache", havingValue = "true")public CacheService cacheService() {return new RedisCacheService();}// 当容器中不存在CacheService时,注册默认的LocalCacheService@Bean@ConditionalOnMissingBean(CacheService.class)public CacheService defaultCacheService() {return new LocalCacheService();}// 当类路径存在HikariDataSource时,注册数据源@Bean@ConditionalOnClass(com.zaxxer.hikari.HikariDataSource.class)public DataSource hikariDataSource() {return new com.zaxxer.hikari.HikariDataSource();}}
五、实战案例:整合配置类注解开发
以 “数据源配置” 为例,整合上述注解实现灵活配置:
1. 定义属性绑定类
import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.validation.annotation.Validated;import javax.validation.constraints.NotEmpty;import javax.validation.constraints.Max;@ConfigurationProperties(prefix = "app.datasource")@Validatedpublic class DataSourceProperties {@NotEmpty(message = "数据库URL不能为空")private String url;@NotEmpty(message = "用户名不能为空")private String username;private String password;@Max(value = 20, message = "最大连接池不能超过20")private int maxPoolSize = 10; // 默认值// getter/setter省略}
2. 配置类实现条件装配
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.ImportResource;import org.springframework.context.annotation.PropertySource;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;@Configuration(proxyBeanMethods = false)@EnableConfigurationProperties(DataSourceProperties.class) // 启用属性绑定@PropertySource("classpath:db-custom.properties") // 加载自定义配置// @ImportResource("classpath:legacy-db.xml") // 按需导入XML配置public class DataSourceConfig {// 当存在HikariDataSource类时,注册Hikari数据源@Bean@ConditionalOnClass(com.zaxxer.hikari.HikariDataSource.class)@ConditionalOnMissingBean(DataSource.class) // 避免重复注册public DataSource hikariDataSource(DataSourceProperties properties) {com.zaxxer.hikari.HikariDataSource dataSource = new com.zaxxer.hikari.HikariDataSource();dataSource.setJdbcUrl(properties.getUrl());dataSource.setUsername(properties.getUsername());dataSource.setPassword(properties.getPassword());dataSource.setMaximumPoolSize(properties.getMaxPoolSize());return dataSource;}}
3. 配置文件(db-custom.properties)
app.datasource.url=jdbc:mysql://localhost:3306/mydbapp.datasource.username=adminapp.datasource.password=admin123app.datasource.max-pool-size=15
六、避坑指南:配置类使用注意事项
- 配置类扫描范围:Spring Boot 默认扫描主启动类所在包及其子包下的配置类,若配置类在其他包,需通过
@SpringBootApplication(scanBasePackages = "com.example.config")
指定扫描范围。 - @Bean 方法调用陷阱:当
proxyBeanMethods=true
(默认)时,配置类内部调用 @Bean 方法会返回容器中的单例 Bean;若proxyBeanMethods=false
,则返回新实例,需根据依赖关系选择。 - 条件注解优先级:多个条件注解同时存在时,需满足所有条件才会注册 Bean(逻辑与关系)。
- 属性绑定优先级:配置文件优先级从高到低为:命令行参数 > 系统环境变量 > application.yml(当前目录) > application.properties(类路径) > 自定义配置文件。
- 避免循环依赖:配置类中 @Bean 方法的依赖关系需清晰,避免 A 依赖 B、B 依赖 A 的循环依赖场景。
总结
Spring Boot 配置类注解通过@Configuration
、@Bean
构建基础,借助@Import
、@PropertySource
扩展配置资源,利用@ConfigurationProperties
实现属性绑定,通过@Conditional
系列注解实现按需装配,形成了一套灵活高效的配置体系。掌握这些注解的核心用法与组合技巧,能大幅简化配置代码,提升项目的可维护性与扩展性。建议结合实际场景多动手实践,深入理解注解背后的设计思想。