在 Spring Boot 开发中,配置类是替代传统 XML 配置的核心载体,通过一系列注解可实现 Bean 注册、属性绑定、条件装配等关键功能。本文将深入解析常用配置类注解,结合示例代码与实战场景,帮你彻底掌握配置类的使用技巧。
声明当前类为配置类,相当于传统 Spring 的applicationContext.xml
文件,Spring 容器会自动扫描并加载该类中的配置。
import org.springframework.context.annotation.Configuration;
// 标记当前类为配置类
@Configuration
public class AppConfig {
// 配置内容(如@Bean注解定义Bean)
}
+ **proxyBeanMethods 属性**:Spring Boot 2.x 新增,默认值为`true`。
// 无Bean依赖场景,设置proxyBeanMethods=false优化性能
@Configuration(proxyBeanMethods = false)
public class SimpleConfig {
@Bean
public User user() {
return new User();
}
}
true
(默认):配置类会被动态代理,类中 @Bean 方法调用时会返回容器中已存在的 Bean 实例(保证单例)。false
:配置类不会生成代理,@Bean 方法调用时会创建新实例,适用于无依赖的简单配置,可提升启动性能。示例:@Component
的区别:@Configuration
本质是@Component
的子类,但前者更强调 “配置功能”,且支持 proxyBeanMethods 特性。在配置类中定义方法,方法返回值会被注册为 Spring 容器中的 Bean,默认 Bean 名称为方法名。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class BeanConfig {
// 注册名为"userService"的Bean,类型为UserService
@Bean
public 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,示例:
@Bean
public OrderService orderService(UserService userService) {
// 注入UserService依赖
OrderService orderService = new OrderService();
orderService.setUserService(userService);
return orderService;
}
在一个配置类中导入其他配置类、普通类或特定接口实现类,无需被导入类标注`@Configuration`。
// 配置类1
@Configuration
public class DbConfig {
@Bean
public DataSource dataSource() {
return new HikariDataSource();
}
}
// 配置类2:导入DbConfig,无需再扫描DbConfig
@Configuration
@Import(DbConfig.class)
public class AppMainConfig {
// 可直接使用DbConfig中注册的DataSource
}
// 普通类(无任何注解)
public class LogService {
public void log() {
System.out.println("日志输出");
}
}
// 配置类导入普通类,LogService会被注册为Bean
@Configuration
@Import(LogService.class)
public class AppConfig {
}
// 自定义ImportSelector,指定要导入的类
public class MyImportSelector implements ImportSelector {
@Override
public String\[] selectImports(AnnotationMetadata importingClassMetadata) {
// 返回要导入的类的全限定名数组
return new String\[]{"com.example.service.CacheService"};
}
}
// 配置类导入Selector
@Configuration
@Import(MyImportSelector.class)
public class AppConfig {
}
兼容传统 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>
将配置文件(如 application.yml/application.properties)中的属性批量绑定到 Java 类的字段上,替代繁琐的@Value
注解。
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省略
}
app:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
max-pool-size: 10 # 支持"-"分隔符,自动映射到maxPoolSize
+ 方式一:在绑定类上添加`@Component`(如上例)。 + 方式二:在配置类上添加`@EnableConfigurationProperties`:
@Configuration
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceConfig {
// 可注入DataSourceProperties使用
@Bean
public 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
}
加载类路径下的自定义配置文件(非默认的 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=MyApp
custom.version=1.0.0
factory
:@PropertySource(value = "classpath:custom.yml", factory = YamlPropertySourceFactory.class)
(需自定义YamlPropertySourceFactory
,或引入 Spring Boot 扩展依赖)
条件注解用于根据特定条件决定 Bean 是否注册到容器中,核心是@Conditional
接口,Spring Boot 提供了多种开箱即用的实现。
注解 | 作用 | 示例 |
---|---|---|
@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 方法上 |
@Configuration
public 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();
}
}
以 “数据源配置” 为例,整合上述注解实现灵活配置:
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")
@Validated
public 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省略
}
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;
}
}
app.datasource.url=jdbc:mysql://localhost:3306/mydb
app.datasource.username=admin
app.datasource.password=admin123
app.datasource.max-pool-size=15
@SpringBootApplication(scanBasePackages = "com.example.config")
指定扫描范围。proxyBeanMethods=true
(默认)时,配置类内部调用 @Bean 方法会返回容器中的单例 Bean;若proxyBeanMethods=false
,则返回新实例,需根据依赖关系选择。Spring Boot 配置类注解通过@Configuration
、@Bean
构建基础,借助@Import
、@PropertySource
扩展配置资源,利用@ConfigurationProperties
实现属性绑定,通过@Conditional
系列注解实现按需装配,形成了一套灵活高效的配置体系。掌握这些注解的核心用法与组合技巧,能大幅简化配置代码,提升项目的可维护性与扩展性。建议结合实际场景多动手实践,深入理解注解背后的设计思想。