Skip to content
Welcome
Go back

Spring @Configuration 配置类完全指南

Edit page

前言

Spring 中配置类(@Configuration)是替代传统 applicationContext.xml 的现代方案,从 Spring 3.0 开始引入。今天我们来系统地梳理它的写法。

1. 核心注解

@Configuration

标记一个类为 Spring IoC 容器的配置类:

@Configuration
public class AppConfig {
    
    @Bean
    public DataSource dataSource() {
        return new HikariDataSource();
    }
}

@Bean

告诉 Spring:方法的返回值需要注册为容器中的一个 Bean。

2. 三种 Bean 注册方式对比

方式注解适用场景
配置类 + @Bean@Configuration + @Bean第三方类库(无法修改源码)
组件扫描@ComponentScan + @Service/@Repository自己项目内的类
@Import@Import(OtherConfig.class)拆分/组合多个配置类

示例:第三方类(@Bean 方式)

@Configuration
public class RedisConfig {
    
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
        return template;
    }
}

3. 配置类常用组合

3.1 读取配置文件

@Configuration
@PropertySource("classpath:application.yml")
public class AppConfig {
    
    @Value("${database.url}")
    private String dbUrl;
    
    @Value("${database.username}")
    private String dbUser;
}

3.2 开启特定功能

@Configuration
@EnableTransactionManagement    // 开启声明式事务
@EnableAspectJAutoProxy        // 开启 AOP
@EnableScheduling              // 开启定时任务
public class RootConfig {
}

3.3 条件化配置

@Configuration
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
public class CacheConfig {
    
    @Bean
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager();
    }
}

4. 多层架构下的配置拆分

实际项目中推荐按功能拆分配置类:

com/example/
├── config/
│   ├── DatabaseConfig.java     // 数据源、JPA/MyBatis
│   ├── SecurityConfig.java     // Spring Security
│   ├── WebMvcConfig.java       // 拦截器、CORS
│   └── AppConfig.java          // 通用 Bean
├── service/
├── repository/
└── controller/

组合方式:@Import

@Configuration
@Import({DatabaseConfig.class, SecurityConfig.class, WebMvcConfig.class})
public class AppConfig {
}

或者使用 @ComponentScan 自动扫描 config 包。

5. 注入依赖的几种姿势

5.1 构造器注入(推荐)

@Configuration
public class AppConfig {
    
    private final DataSource dataSource;
    
    public AppConfig(DataSource dataSource) {
        this.dataSource = dataSource;
    }
    
    @Bean
    public JdbcTemplate jdbcTemplate() {
        return new JdbcTemplate(dataSource);
    }
}

5.2 方法参数注入

@Configuration
public class AppConfig {
    
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

5.3 字段注入(不推荐)

@Configuration
public class AppConfig {
    @Autowired
    private DataSource dataSource;  // ❌ 配置类中尽量避免
}

6. @Configuration 与 @Component 的区别

很多新手会混淆这两者:

特性@Configuration@Component
代理CGLIB 代理(单例保证)无代理
@Bean 调用返回同一个实例(单例)返回新实例
用途定义配置/Bean普通组件
内部方法调用@Bean 方法互相调用走代理不走代理

举个栗子 🌰:

@Configuration
public class AppConfig {
    
    @Bean
    public A a() {
        return new A(b());  // 调用 b() 走代理,返回单例
    }
    
    @Bean
    public B b() {
        return new B();
    }
}

7. 实战:一个完整的配置类

@Configuration
@EnableTransactionManagement
@PropertySource("classpath:application.yml")
@ComponentScan(basePackages = "com.example")
public class AppConfig {
    
    @Value("${db.url}")
    private String dbUrl;
    
    @Value("${db.username}")
    private String dbUser;
    
    @Value("${db.password}")
    private String dbPassword;
    
    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(dbUrl);
        config.setUsername(dbUser);
        config.setPassword(dbPassword);
        return new HikariDataSource(config);
    }
    
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

8. 常见坑点

❌ 配置类加上 final

@Configuration 依赖 CGLIB 代理,final 类无法被代理。

❌ 内部 private @Bean 方法

@Bean 方法不能是 private 的。

✅ 推荐的做法

总结

Spring 配置类(@Configuration)是 Spring 框架的基石之一。掌握它的写法不仅能让你告别 XML,还能更深入地理解 IoC 容器的工作原理。从单类配置到多模块拆分,再到条件化装配,这些都是在实际项目中每天都会用到的技能。


Edit page
Share this post:

Previous Post
Vibe Coding 不是放飞 AI,而是按风险分配控制权