# @Configuration与@Component区别是什么?

在 Spring 框架中,@Configuration@Component 都是用于将类定义为 Spring 容器的 Bean,但它们在用途和行为上有显著区别。

# 基本定位

  • @Component:通用的组件注解。当一个类被标记为 @Component(或其派生注解 @Service@Repository@Controller),Spring 会将其作为一个普通的 Bean 注册到容器中。它适合那些不承担特殊配置职责的普通业务类。
  • @Configuration配置类注解。它本身被 @Component 元注解修饰,所以 @Configuration 类也是一个 Spring Bean。但它的核心职责是定义 Bean 的创建逻辑——通常通过 @Bean 方法暴露 Bean 实例。

# @Bean 方法的行为差异(最关键的区别)

当一个类中使用 @Bean 方法定义 Bean 时:

  • @Configuration 类中:这些 @Bean 方法会被 Spring 通过 CGLIB 动态代理 增强。这意味着:
    • 即使你在方法内部多次调用其他 @Bean 方法,返回的始终是同一个容器管理的单例实例(默认单例作用域)。
    • 保证了 Bean 之间的依赖关系符合预期的单例语义。
  • 在普通 @Component 类中@Bean 方法不会被代理。如果在一个 @Component 类中调用另一个 @Bean 方法,那只是一个普通的 Java 方法调用,每次都会新建实例,破坏了单例语义。

示例对比

@Configuration
public class ConfigClass {
    @Bean
    public A a() {
        return new A();
    }
    @Bean
    public B b() {
        // 通过方法调用获取 A → 由于代理,实际从容器中获取单例的 A
        return new B(a());
    }
}

@Component
public class ComponentClass {
    @Bean
    public A a() {
        return new A();
    }
    @Bean
    public B b() {
        // 这里是普通 Java 调用,会创建新的 A 实例,不是容器中的单例
        return new B(a());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

ComponentClass 中,b() 方法里调用 a() 会生成一个新的 A 对象,而不是容器中已注册的那个。

# 使用场景

  • @Configuration:专门用于配置类,集中管理一组 Bean 的定义,特别是当 Bean 之间有复杂依赖或需要保证单例时。通常配合 @Bean@Import@PropertySource 等使用。
  • @Component:用于普通的自动检测类(如服务、DAO、控制器)。如果需要在普通组件中通过 @Bean 定义对象,通常是违反设计直觉的,更推荐使用 @Configuration

# 内部处理的差异

  • Spring 在处理 @Configuration 时会创建 CGLIB 代理子类,拦截 @Bean 方法的调用,确保 Bean 的生命周期管理。
  • @Component 不会进行这种代理处理,因此性能开销略小,但牺牲了 @Bean 方法的拦截能力。

# 总结表

特性 @Configuration @Component
自身是否被 @Component 元注解 是(被其他注解间接使用)
主要用途 定义 Bean 配置类 标记普通组件类
@Bean 方法行为 被 CGLIB 代理,保证单例 普通方法调用,不保证单例
是否推荐使用 @Bean 强烈推荐,标准用法 可以,但非典型,容易出错
典型场景 @Configuration + @Bean @Service@Repository

一句话概括@Configuration 是专门用于配置 Bean 定义的增强型组件,它通过代理保证了 @Bean 方法的单例语义;而 @Component 是通用的普通组件注解,不具备这种特殊处理。

Last Updated: 6/12/2026, 4:20:22 AM