@Configuration 和 @Component 有什么区别?为什么有些配置类要用 @Configuration?

Spring注解配置:@Configuration 和 @Component 区别及原理详解 Indexed​/***/​复制代码@Component​​​复制代码从定义来看, @Configuration 注解本质上还是 @Component,因此 @ComponentScan 能扫描到@Configuration 注解的类。@Component在Spring中是代表LITE模式的配置注解,这种模式下的注解不会被Spring所代理,就是一个标准类,如果在这个类中有@Bean标注的方法,那么方法间的相互调用,其实就是普通Java类的方法的调用。 阅读详情

简单来说:

  • @Component 是一个通用的构造型注解,它告诉 Spring:“请把我这个类扫描成一个 Bean”。
  • @Configuration 是一个特殊的 @Component。它不仅能让类成为 Bean,还开启了一项“魔法”功能:确保 @Bean 方法返回的都是由容器管理的单例 Bean。

快速对比

特性@Component@Configuration
本质通用 Bean 标记特殊的 Bean 标记
继承关系无@Configuration 自身被 @Component 元注解标注
核心目的标记一个普通的业务组件(Service, Repository等)专门用于定义 Bean 的配置类
@Bean 方法行为Lite Mode(轻量模式)Full Mode(完整模式)
背后原理普通的 Bean通过 CGLIB 代理增强

关键区别:@Bean 方法的行为

这个区别是理解两者的关键。让我们通过一个例子来揭示这个“魔法”。

场景:我们有一个 Car Bean,它依赖于一个 Engine Bean。我们希望整个应用中只有一个 Engine 实例。

1. 使用 @Configuration(正确的方式)
@Configuration
public class AppConfig {

    @Bean
    public Engine engine() {
        System.out.println(">>> 创建 Engine Bean...");
        return new Engine();
    }

    @Bean
    public Car car() {
        System.out.println(">>> 创建 Car Bean...");
        // 这里直接调用了 engine() 方法
        Engine carEngine = this.engine(); 
        return new Car(carEngine);
    }
}

运行结果:

>>> 创建 Engine Bean...
>>> 创建 Car Bean...

分析:

  • engine() 方法只被调用了一次!
  • 当我们创建 car Bean 并调用 this.engine() 时,Spring 并没有真的去执行 engine() 方法体里的 new Engine()。
  • 为什么? 因为 AppConfig 类被 @Configuration 标记了,Spring 在启动时会为它创建一个 CGLIB 代理子类(比如 AppConfig$$EnhancerBySpringCGLIB$$...)。
  • 这个代理类重写了所有的 @Bean 方法。当你调用 this.engine() 时,代理会拦截这个调用,并检查 IoC 容器中是否已经存在一个名为 “engine” 的 Bean。如果存在,就直接返回容器中的那个单例实例;如果不存在,才执行原始方法体来创建它。
  • 结论:@Configuration 保证了无论你调用 @Bean 方法多少次,返回的都是同一个由容器管理的单例对象。

2. 使用 @Component(错误或危险的方式)

现在,我们把 @Configuration 换成 @Component,其他代码完全不变。

@Component // 这里换成了 @Component
public class AppConfigLite {

    @Bean
    public Engine engine() {
        System.out.println(">>> 创建 Engine Bean...");
        return new Engine();
    }

    @Bean
    public Car car() {
        System.out.println(">>> 创建 Car Bean...");
        // 这里直接调用了 engine() 方法
        Engine carEngine = this.engine(); 
        return new Car(carEngine);
    }
}

运行结果:

>>> 创建 Engine Bean...
>>> 创建 Car Bean...
>>> 创建 Engine Bean... 

分析:

  • engine() 方法被调用了两次!
  • 为什么? 因为 AppConfigLite 被 @Component 标记,Spring 只把它当作一个普通的 Bean。它不会为这个类创建 CGLIB 代理。
  • 因此,当 car() 方法内部调用 this.engine() 时,它就是一个普通的 Java 方法调用。它会完整地执行 engine() 方法体,即 new Engine(),从而创建了一个全新的、不受 Spring 容器管理的 Engine 实例。
  • 结论:在 @Component 类中调用 @Bean 方法,会绕过容器的管理,导致每次都创建新对象,破坏了单例作用域。

为什么有些配置类要用 @Configuration?

答案就是为了解决上面例子中的问题:确保 Bean 之间的依赖关系正确无误。

一个经典的真实场景是 DataSource 和 JdbcTemplate:

@Configuration
public class DatabaseConfig {

    @Bean
    public DataSource dataSource() {
        // 创建并返回一个 DataSource Bean
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("...");
        ds.setUsername("...");
        ds.setPassword("...");
        return ds;
    }

    @Bean
    public JdbcTemplate jdbcTemplate() {
        // JdbcTemplate 依赖于 DataSource
        // 我们希望它使用的是上面由容器管理的那个单例 DataSource
        return new JdbcTemplate(this.dataSource()); 
    }
    
    @Bean

    public MyTransactionManager myTransactionManager() {
        // 另一个组件也依赖于同一个 DataSource
        return new MyTransactionManager(this.dataSource());
    }
}

在这个例子中,jdbcTemplate() 和 myTransactionManager() 都需要 DataSource。因为我们用了 @Configuration,所以两次 this.dataSource() 调用都会被 Spring 的代理拦截,并返回同一个由容器管理的 DataSource 实例。

如果这里错误地使用了 @Component,那么 JdbcTemplate 和 MyTransactionManager 将会各自持有一个全新的、独立的、不受容器管理的 DataSource 实例,这可能会导致连接池失效、事务管理混乱等一系列灾难性问题。

总结

@Configuration (Full Mode)@Component (Lite Mode)
用途首选,用于定义Bean的配置类,特别是当Bean之间有依赖关系时。用于普通的业务组件。不推荐在其中定义有相互依赖的 @Bean 方法。
行为通过CGLIB代理,保证 @Bean 方法调用返回容器中的单例Bean。普通Java方法调用,每次都创建新对象,绕过容器管理。
何时使用只要你的配置类里有 @Bean 方法,特别是它们之间有调用关系,就必须使用 @Configuration。当你的类只是一个简单的业务组件(如Service),或者你的配置类里的 @Bean 方法完全独立,没有相互调用时(但依然不推荐)。

所以,请记住这个黄金法则:任何用于定义 Bean(即包含 @Bean 方法)的类,都应该使用 @Configuration 注解,以确保其行为符合 Spring IoC 容器的预期。

【论文笔记】Beyond Low-frequency Information in Graph Convolutional Networks 文章目录1. Abstract2. Introduction低频和高频信号作用FAGCN怎么设计3. An Experimental Investigation4. Model4.1 filter定义4.2 Aggregation4.3 Problems of signal combination4.4 Spatial vision of FAGCN4.5 系数αijG\alpha_{i j}^{G}αijG​4.6 模型整体框架FAGCN的表达能力实验 本文发表在AAAI-21上 论文地址:https: 阅读详情

相关推荐

C#实战:如何用TSCLIB.dll实现TSC打印机的状态监控与异常处理(附完整代码)

本文详细介绍了如何利用C#和TSCLIB.dll构建企业级TSC打印机状态监控与智能异常处理系统。通过解析十六进制状态码、设计高可靠性的轮询引擎以及实现事件驱动的报警机制,开发者可以打造一个稳定、可观测的打印服务,有效保障物流仓储、生产制造等高频打印场景的业务连续性。

weixin_29227585的博客 64

深入@component注解与@Configuration

1、@Configuration 从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。 注意:@Configuration注解的配置类有如下要求: 1、@Configuration不可以是final类型;

weixin_41438466的博客 6871

详细教程:如何使用elasticsearch 8.x进行向量搜索

大模型的热度使得向量数据库和embedding也成了ai领域的热门话题,有别于从头开始训练一个大模型或基于基础模型进行微调的方式,embedding检索相关上下文是对大模型进行定制的各种方法中成本最低、技术实现最便捷的方式。从技术实现的角度,

qq_50790981的博客 1万+

@Configuration和@Component

@Configuration注解能够使得加了它的对应的配置类在spring容器中是一个cglib代理bean,让配置类实例变成cglib代理实例的作用就是防止@Bean方法B又调用@Bean方法A的这种场景破坏了bean的单例性。解决这种场景的原理就是在spring实例化@Bean方法B对应的bean的时候,会通过反射调用配置类的@Bean方法B,在反射调用之前@Bean方法B放到currentlyInvokedFactoryMethod中,然后由于配置类已经是一个cglib代理对象了,

qq_40708942的博客 6143

ANSYS Fluent 2023R2实战:用欧拉多相流模型搞定流化床模拟(附详细参数避坑)

本文详细解析了ANSYS Fluent 2023R2中欧拉多相流模型在流化床模拟中的应用,包括模型选择、材料属性设置、相间作用力配置及初始化技巧。特别针对高颗粒浓度工况提供参数优化方案,帮助工程师提升模拟精度与效率,适用于化工、能源等领域的流化床反应器设计。

weixin_30938149的博客 268

智慧工地算法视频分析服务器区域入侵检测AI视频分析技术在煤矿的实战应用

通过实时分析和处理井下视频资料,智慧矿山算法视频分析服务器不仅能够及时发现并预警人员违规行为和设备异常状况,还能够通过智能分析预防潜在的安全风险,从而显著提高煤矿的安全管理水平和生产效率。

EasyDarwin开源社区技术博客 560

Spring底层原理之bean的加载方式三 用注解声明配置类 以及@Configuration 和 @Component 的区别

@Configuration @Configuration是 Spring Framework 中的一个注解,它用于指示该类是一个配置类,它的作用类似于传统的 XML 配置文件。具体来说,它的主要功能有以下几点: 定义配置类:使用 @Configuration 注解的类可以提供 bean 的定义和其他 Spring 配置的定义。 声明 Bean:在配置类中,可以使用 @Bean 注解声明 bean。这些 bean 将由 Spring 容器管理,并可以在应用程序中通过依赖注入来使用。 替代 XML 配置

多多的博客 11万+

LangGraph的容错机制:从节点失败到图级回滚

核心概念铺垫:讲解LLM应用容错与事务性的核心概念(幂等性、重试策略、降级策略、快照、回滚、原子性、一致性、隔离性、持久性、最终一致性),对比LangGraph容错机制与传统数据库ACID事务、Apache Airflow/Kubernetes Workflow/Kubeflow Pipelines容错机制的异同;LangGraph容错机制的演进历史:用markdown表格梳理LangGraph从0.0.1到1.5.0(截止202X年X月)的容错机制发展历程;节点级别的容错:重试与降级。

AI Python 编程之道的博客 172

@Configuration与@Component作为配置类的区别

@Configuration注解的类: @Configuration public class MyBeanConfig { @Bean public Country country(){ return new Country(); } @Bean public UserInfo userInfo(){ return new UserInfo(country()...

weixin_44101221的博客 419

【经验&技巧】IBIS AMI模型眼图仿真问题探讨

在ADS的仿真环境中,不论发送和接收的AMI模型是否为true或者false,都可以将通道仿真设置为统计模式,但是,如果有一方的Init函数为false,在统计模式下,处于false状态的模型将不能执行其自带的后处理功能,如下图所示,左边的统计模式和右边的逐比特模式眼图存在明显的差异,原因在于,接收端的init函数为false导致在统计模式中不能对眼图进行DFE处理,换言之,此时统计模式下的眼图就是未经任何处理的“生图”。

一只豌豆象的博客 1766

Langchain cannot connect with Azure SQL Database

Langchain 无法连接到 Azure SQL 数据库

suiusoar 633

@Configuration与@Component作为配置类的区别详解

目录1.@Configuration注解的类:2.@Component注解的类:3.测试4.结果4.1 @Component的结果4.2 @Configuration的结果5.分析5.1 @Component的类没有动态代理,但可以用@Qualifier或者@Resource 前言:这篇文章主要介绍了@Configuration与@Component作为配置类的区别详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 1.@Confi

qq_34246965的博客 981

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Spring 中@Component和@Configuration作为配置类的区别

https://my.oschina.net/guangshan/blog/1807721

a15237851433的博客 647

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

@component注解与@Configuration的理解

@component注解与@Configuration的理解 首先来解释下@Configuration在来解释@component再来讲述两者的区别 @Configuration 从Spring3.0,@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationConte...

baidu_41634343的博客 1万+

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

@Component和@Configuration配置类的区别

@Component和@Configuration区别是什么呢,哈,区别来了 后者功效大于前者 后者基于CGLIB代理,会直接从上下文调用并返回bean(单例),而不是再次执行方法(new对象) 后者在项目启动后,一切已初始化就绪,且只会初始化一次;前者在项目启动后,每次调用都会被初始化 后者处理逻辑较为复杂的业务场景,比如:注入bean(@bean);前者“简单粗暴”,类型与@Controll...

qq_36206259的博客 481

Spring 核心机制:到底什么样的类才算配置类?@Configuration 与 @Component 的本质区别

本文系统梳理了Spring配置类的核心概念与实现形式。配置类(@Configuration)是Spring容器进行资源加载和Bean定义的核心入口,与普通组件类(@Component)存在本质区别。文章详细解析了配置类的定义标准、实现方式(标准注解式、简化注解式、非注解式、间接导入式)及其适用场景,深入探讨了@Bean和@Configuration注解的作用原理与使用规范。同时对比了不同配置形式(@Component+@Bean、XML配置等)的差异与优劣,强调@Configuration作为官方推荐方式在

l7_yuqi的博客 453

Spring @Configuration 和 @Component 区别

Spring @Configuration 和 @Component 区别 一句话概括就是 @Configuration 中所有带 @Bean 注解的方法都会被动态代理,因此调用该方法返回的都是同一个实例。 下面看看实现的细节。 @Configuration 注解: @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration {

qq_43842093的博客 511

@Component和@Configuration作为配置类的差别

随着spingboot的大火,注解式配置受到了大家的热烈欢迎,而@Component和@Configuration都可以作为配置类,之前一直都没觉得这两个用起来有什么差别,可能有时程序跑的和自己想的有所区别也没注意到。 直到看到这篇文章:https://my.oschina.net/guangshan/blog/1807721 。我意识到@Component和@Configuration是有区别...

一号搬砖手的博客 10万+

@Configuration 和 @Component 到底有啥区别?

Spring 注解中 @Configuration 和 @Conponent 区别总结为一句话就是: @Configuration 中所有带 @Bean 注解的方法都会被动态代理(cglib),因此调用该方法返回的都是同一个实例。而 @Conponent 修饰的类不会被代理,每实例化一次就会创建一个新的对象。

S mile0804的博客 2万+

@bean注解和@component注解的区别_Spring 中的一些注解

这也是很久之前写的,不出所料的话今天依旧是水文章的一天,就不该年初立flag。本文打算介绍几个不太容易说出其区别,或者用途的 Spring 注解,比如@Component与@Bean的比较,@ControllerAdvice是如何处理自定义异常的等等。Spring 中的一些注解1.@Component和@Bean的区别是什么?1.作用对象不同:@Component注解...

weixin_35544490的博客 2万+

@configuration和@component之间的区别是什么?

@configuration和@component之间的区别是什么?

weixin_44119329的博客 2万+

@Component与@Configuration区别联系

d

lzh的博客 631

@Component 和 @Bean 和 @configuration的区别

@Component 和 @Bean 和 @configuration的区别

beiback的博客 568
上一篇: @Component, @Service, @Repository, @Controller 有什么本质区别吗?为什么需要这么多不同的注解?
下一篇: @Primary 是做什么的?
冰糖心书房
博客等级 码龄15年 6014粉丝 690原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值