【Spring】@Component VS @Configuration


在 Spring 生态开发中,**@Component** 和 @Configuration 是管理 Bean 实例、实现依赖注入的核心注解,也是 Java 后端开发必须吃透的基础知识点。

二者看似都是向 Spring 容器注册组件,底层逻辑、使用场景、生效机制却天差地别。

复制代码
====== 🌟 青柠来相伴,代码更简单。🌟 ======
📚 本文所有内容,我都整理成了文档资料。👇
🎯 搜索【青柠代码录】,关键字:青柠合集
🚀 即可查看所有博客文章 ~
====== 🌟 =================  🌟 ======

一、基础认知

@Component我是一个普通组件,让 Spring 管理我就行,适用于所有业务类、工具类。

@Configuration我是一个配置管家,负责给 Spring 批量注册 Bean,适用于全局配置、第三方集成。

二者是 Spring 容器管理的基础,正确使用是实现解耦、规范开发的核心前提。

1. @Component 注解

复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Component {
    String value() default "";
}
  • 核心作用通用型组件注解,将普通 Java 类,标记为 Spring 容器管理的 Bean,是 Spring 中最基础的组件注册注解。
  • 衍生注解:@Controller(Web 层)、@Service(业务层)、@Repository(数据层),均是 @Component 的语义化扩展,底层逻辑完全一致。
  • 注册方式 :Spring 通过 组件扫描(@ComponentScan) ,自动扫描标注该注解的类,实例化后存入单例池。

2. @Configuration 注解

复制代码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    String value() default "";
    boolean proxyBeanMethods() default true;
}
  • 核心作用配置类专用注解 ,标记一个类为 Spring 配置类,替代传统 XML 配置文件,用于 集中定义、组装 Bean
  • 底层特性 :本身被 @Component 修饰,本质也是一个组件,但具备 代理增强能力。
  • 核心能力:支持在类内部,通过 @Bean 注解,手动创建 Bean,实现复杂 Bean 的初始化、依赖注入。

二、核心区别

对比维度 @Component @Configuration
注解本质 普通组件注解 配置类注解(继承 @Component)
核心用途 注册业务 / 工具类 Bean 定义配置类、手动创建 / 组装 Bean
Bean 定义方式 直接标注在类上,自动实例化 标注在类上,内部通过 @Bean 方法定义 Bean
代理机制 无代理,原生对象 默认开启 CGLIB 代理(proxyBeanMethods=true)
方法调用特性 普通方法调用,每次创建新对象 代理调用,保证 Bean 单例(容器内唯一)
依赖注入方式 自动注入(@Autowired) 支持方法参数注入、成员变量注入
使用场景 业务层、工具类、通用组件 配置类、第三方 Bean 注册、全局配置
生命周期管理 标准 Spring Bean 生命周期 配置类优先初始化,优先于普通组件
多实例支持 可配合 @Scope 定义多例 内部 @Bean 默认单例,可自定义作用域
优先级 业务开发主流使用 框架配置、第三方集成、全局配置专用

三、底层原理

1. @Component 底层处理流程

  1. Spring 启动时, ComponentScanAnnotationParser 解析 @ComponentScan 路径;
  2. 扫描所有标注 @Component(含衍生注解)的类,封装为 BeanDefinition
  3. 容器根据 BeanDefinition ,调用构造方法实例化对象;
  4. 完成依赖注入、初始化后,将 原生对象存入单例池。

关键:无任何代理增强,类中的方法调用,为原生 Java 方法调用。

2. @Configuration 底层处理流程

  1. 因标注 @Component,优先被扫描为配置类 BeanDefinition
  2. ConfigurationClassPostProcessor 后置处理器增强配置类:
  • 默认开启 proxyBeanMethods=true,使用 **CGLIB 动态代理 ,**创建配置类代理对象;
  • 拦截内部 @Bean 方法,保证多次调用返回同一个单例 Bean;
  1. 解析内部所有 @Bean 方法,注册为独立 Bean;
  2. 代理对象存入容器,保证 Bean 方法调用的单例性。

核心特性配置类代理模式,解决 @Bean 方法相互调用时的多例问题。

四、案例实战

场景 1:@Component 注册通用业务组件

适用场景:自定义工具类、业务辅助类、无分层的通用组件。

复制代码
import org.springframework.stereotype.Component;

/**
 * 字符串工具类:注册为 Spring Bean
 * 开发中,通用工具类优先使用 @Component
 */
@Component
public class StringUtils {

    /**
     * 判空方法
     */
    public boolean isEmpty(String str) {
        return str == null || str.trim().isEmpty();
    }
}

注入使用

复制代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    // 自动注入 @Component 修饰的 Bean
    @Autowired
    private StringUtils stringUtils;

    public void checkUsername(String username) {
        if (stringUtils.isEmpty(username)) {
            throw new RuntimeException("用户名不能为空");
        }
    }
}

场景 2:@Configuration 定义配置类 + 注册第三方 Bean

适用场景:集成第三方框架(Redis、MQ、MyBatis)、自定义线程池、全局配置类。

复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 线程池配置类
 * 开发中,所有第三方 Bean、全局配置均使用 @Configuration
 */
@Configuration
public class ThreadPoolConfig {

    /**
     * 定义全局单例线程池 Bean
     * @Bean 注解:方法返回值注册为 Spring Bean
     * 方法名默认作为 Bean 名称,可通过 @Bean("customExecutor") 自定义
     */
    @Bean
    public ExecutorService taskExecutor() {
        return Executors.newFixedThreadPool(10);
    }

    /**
     * 依赖注入:直接将上方 Bean 作为参数注入
     * 配置类内部依赖自动关联,无需手动 @Autowired
     */
    @Bean
    public TaskService taskService(ExecutorService taskExecutor) {
        TaskService taskService = new TaskService();
        taskService.setExecutor(taskExecutor);
        return taskService;
    }
}

场景 3:核心坑点:proxyBeanMethods 代理机制

错误示例(无代理,产生多例 Bean)

复制代码
// 关闭代理:proxyBeanMethods = false
@Configuration(proxyBeanMethods = false)
public class TestConfig {

    @Bean
    public User user() {
        return new User();
    }

    @Bean
    public Order order() {
        Order order = new Order();
        // 此处调用 user() 方法,会创建新的 User 对象,破坏单例!
        order.setUser(user());
        return order;
    }
}

问题 :关闭代理后,方法调用为原生调用,每次 user() 都会 new 新对象,导致容器内存在多个 User 实例。

正确示例(默认开启代理,保证单例)

复制代码
// 默认:proxyBeanMethods = true,开启 CGLIB 代理
@Configuration
public class TestConfig {

    @Bean
    public User user() {
        return new User();
    }

    @Bean
    public Order order() {
        Order order = new Order();
        // 代理拦截:调用的是容器中的单例 User,不会创建新对象
        order.setUser(user());
        return order;
    }
}

规范

  1. 配置类内部 @Bean 方法相互调用 :必须保留默认 proxyBeanMethods=true
  2. 纯配置类、无内部方法调用:可设置为 false,提升启动性能。

五、开发规范

  1. 分层注解规范
  • Web 层:@Controller
  • 业务层:@Service
  • 数据层:@Repository
  • 通用组件:@Component
  • 配置类:@Configuration
  1. 禁止混用场景
  • 禁止在业务类上使用 @Configuration;
  • 禁止在配置类中编写业务逻辑;
  • 禁止使用 @Component 替代 @Configuration 注册第三方 Bean。
  1. 性能优化规范
  • 无内部 @Bean 方法调用的配置类,添加 proxyBeanMethods = false
  • 组件扫描路径精准配置,避免扫描无关包,提升启动速度。
  1. Bean 依赖规范
  • 配置类中 @Bean 方法 优先使用参数注入,替代 @Autowired;
  • 业务组件中使用 @Autowired 注入 @Component 修饰的 Bean。

本文由mdnice多平台发布

相关推荐
uzong23 分钟前
我研读了 500 个 Spring Boot 生产级代码库,90% 都犯了这 7 个致命错误
后端
xiaobaoyu1 小时前
ssm知识点梳理
后端
IT_陈寒2 小时前
Vite的public文件夹放静态资源?这坑我替你踩了
前端·人工智能·后端
浮游本尊2 小时前
合同同步逻辑
后端
子兮曰2 小时前
别让爬虫白嫖你的导航站了:纯免费,手把手实现加密字体防爬
前端·javascript·后端
阿苟2 小时前
JAVA重点难点
后端
uzong2 小时前
TIOBE 指数:2026 年编程语言排行榜
后端
小村儿2 小时前
连载06 - Hooks 源码深度解析:Claude Code 的确定性自动化体系
前端·后端·ai编程
用户8356290780512 小时前
使用 Python 设置 Excel 数据验证
后端·python
yoyo_zzm3 小时前
Laravel6.x新特性全解析
java·spring boot·后端