从spring源码角度分析@Configuration和@Component区别

11 篇文章 1 订阅
订阅专栏

很多人都用过@Configuration和@Component,但并不一定了解他们的区别,或者所了解到的区别仅限于理论层面,并不知道真实原因,最近本人在学习spring 5.2.x源码,特记录并分享一下。
首先,我们可以看到@Configuration的代码是这样的:
在这里插入图片描述
从图中可以看出,@Configuration这个类是加上了@Component注解的,所以姑且认为@Component有的功能他都有,但是今天的主题是讨论他们不一样的地方。首先通过代码直接测试,然后再分析源码。测试代码如下:

============================= JavaConfig =====================================

package org.springframework.francis.config;

import org.springframework.context.annotation.ComponentScan;

@ComponentScan("org.springframework.francis.bean")
public class JavaConfig {

}

================================ A ==========================================

package org.springframework.francis.bean;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class A {
    @Bean
	public B b() {
		System.out.println("+++++++++++++++++");
		return new B();
	}

	@Bean
	public C c() {
		System.out.println(b());
		return new C();
	}

}

=================================== B =======================================

package org.springframework.francis.bean;

public class B {
}

================================== C ========================================

package org.springframework.francis.bean;

public class C {
}

================================ Test =======================================

package org.springframework.francis;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.francis.bean.A;
import org.springframework.francis.bean.B;
import org.springframework.francis.config.JavaConfig;


public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(JavaConfig.class);
        JavaConfig javaConfig = applicationContext.getBean("javaConfig", JavaConfig.class);
        System.out.println(javaConfig);

        A a = applicationContext.getBean("a", A.class);
        System.out.println(a);

        B b = applicationContext.getBean("b", B.class);
        System.out.println(b);
    }

}

当A.class类上面加的注解为@Configuration时,运行结果如下:
在这里插入图片描述
从图中可以看出,A的地址中包含A$$EnhancerBySpringCGLIB,这说明A类是用spring的cglib代理生成的,然后b()中的+++++++只打印一次,且两次打印B的地址都是一样的,说明B是单例的。

然后,当A.class类上面加的注解为@Component时,运行结果如下:
在这里插入图片描述
从图中可以看出,A的地址并没有$$EnhancerBySpringCGLIB字样,b()中的+++++++打印了两次,且两次打印B的地址不一样,这说明这个过程中创建了两个B对象。

从两个截图我们可以很明显的看出他们的区别,而且像

    @Bean
	public C c() {
		System.out.println(b());
		return new C();
	}

这种场景在开发中是比较常见的,比如我们自定义数据源的时候,经常会看到类似的写法:

    @Bean(name = "masterDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    @Bean(name = "masterTransactionManager")
    @Primary
    public DataSourceTransactionManager masterTransactionManager() {
        return new DataSourceTransactionManager(masterDataSource());
    }

所以遇到类似场景我们就知道该用哪个注解了,而并不是去靠猜和试。而且也不需要这么写:

    @Bean(name = "masterDataSource")
    @Primary
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource masterDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    @Autowired
    private DataSource  masterDataSource;
    
    @Bean(name = "masterTransactionManager")
    @Primary
    public DataSourceTransactionManager masterTransactionManager() {
        return new DataSourceTransactionManager(masterDataSource);
    }

下面我们从源码角度分析为什么会有这种区别,这时候需要将A.class的注解改为@Configuration,然后debug。

我们先直接断点到ConfigurationClassPostProcessor.java的enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory)方法,第一次走第一个for循环时如图:
在这里插入图片描述
然后,我们一直走for循环,直到beanName为a时,我们再看截图:在这里插入图片描述
接着,我们继续往下走:
在这里插入图片描述
一直执行完第一个for循环,进入第二个for循环,如图:
在这里插入图片描述
从几个图中我们可以看出 configClassAttr=full 的才会存入 configBeanDefs 这个map中,在map中的AbstractBeanDefinition才会进入第二个for循环并执行cglib动态代理。进入enhancer.enhance() 后,会调用到ConfigurationClassEnhancer.java的内部类BeanMethodInterceptor的isMatch方法,具体如下图:
在这里插入图片描述
然后我们再看下图:
在这里插入图片描述
这一段注释说明会处理加了@Bean的注解,具体就不分析了,我们姑且先认为加了@Configuration注解的类中加了@Bean注解的方法只会生成单例对象,当然事实也是如此。

下面我们再看为什么 ConfigurationClassPostProcessor.java的enhanceConfigurationClasses()中A 的 configClassAttr = full,我们在ConfigurationClassUtils.java的checkConfigurationClassCandidate()中断点,下面提供一个调用栈,读者就可以很快知道为什么会在这里断点,如图:
在这里插入图片描述
我们可以看到这个方法中有对加了@Configuration注解的处理,当前beanClass为A时,正好满足下图中 if 的逻辑
在这里插入图片描述
到这里,相信大家应该明白spring在启动过程中是怎么处理加了@Configuration注解以及@Configuration和@Component的区别了。
最近看了一下官方文档,其实官方文档对此也有说明:
在这里插入图片描述
同时,如果不想使用@Configuration, 官方 也说明了可以用@Component来代替,但是需要使用构造注入或方法注入,如图:
在这里插入图片描述
示例:
在这里插入图片描述

Spring@Component和@Configuration区别
JAVAQXQ的博客
07-31 842
直接上总结加了@Configuration的类会被CGLIB进行动态代理,不加或者加@Component注解则不会被代理。
Spring 源码解析——@Configuration 作用及其实现原理(一)
Coder Yang
09-21 3668
目录 一、概述 二、相关技术 2.1 @Configuration 作用 2.2 BeanDefinition 和BeanDefinitionMap 2.3 CGLIB 简介 三、源码解析 3.1 概述 3.2register(Bean 注册流程) 3.3 refresh(BeanClass 的替换) 四、内容总结 写文章不易,转载请标明出处。 同时,如果你喜欢我的文...
@Configuration与@Component作为配置类的区别详解
08-25
主要介绍了@Configuration与@Component作为配置类的区别详解,文通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
Spring源码注解篇三:深入理解@Component注解
最新发布
Jeremy程序员
07-15 902
Spring框架作为Java开发不可或缺的一部分,其依赖注入机制的核心是通过注解来实现的。本文将深入探讨Spring@Component及其派生注解的源码实现,分析Spring如何通过类路径扫描(Classpath Scanning)和BeanDefinition的封装来管理Bean的生命周期和依赖。
@Configuration 和 @Component 区别
老照片
01-31 1467
@Configuration 和 @Component 区别
@configuration和@component之间的区别是什么?
weixin_44119329的博客
12-30 2万+
@configuration和@component之间的区别是什么?
@Configuration和@Component区别
夜行僧的博客
04-21 253
@Configuration详解 一、@Configuration @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration { @AliasFor( annotation = Component...
Spring源码解析 – @Configuration配置类及注解Bean的解析
weixin_43493131的博客
10-23 328
分析Spring 容器创建过程时,我们知道容器默认会加载一些后置处理器PostPRocessor,以AnnotationConfigApplicationContext为例,在构造函数初始化reader时,加载默认后置处理器。其 ConfigurationClassPostProcessor这个后置处理器专门处理带有@Configuration注解的类,ConfigurationClassP...
Spring之@Configuration、@Component、@Bean
Hello World
05-20 1630
@Configuration 代表这个类是一个配置类,可理解为用spring的时候xml里面的<beans>标签 @Bean 用来定义一个bean,可以指定初始、销毁方法,及bean范围等,可理解为用spring的时候xml里面的<bean>标签 @ComponentScan 用来扫描指定包下面的注解类,相当于<context:component-scan...
spring源码:@Configuration源码
小小少年的博客
06-23 548
@Configuration注解 在使用spring的时候,如果我们加了一个配置类,通常会在配置类上加上一个@Configuration注解,这个注解的作用,是我们要探讨的内容 结论: 1.加了@Configuration注解的类,我们称之为全配置类,这里之所以这么叫,在后面我会解释(当然) 2.对于加了@Configuration的配置类,spring会为该类生成代理对象(CGLIB代理) 3.配置类加与不加@Configuration,都会注入bean,只是,通过@Bean在配置类注入的bean,有可
@Component和@Configuration作为配置类的差别
热门推荐
一号搬砖手的博客
06-08 9万+
随着spingboot的大火,注解式配置受到了大家的热烈欢迎,而@Component和@Configuration都可以作为配置类,之前一直都没觉得这两个用起来有什么差别,可能有时程序跑的和自己想的有所区别也没注意到。 直到看到这篇文章:https://my.oschina.net/guangshan/blog/1807721 。我意识到@Component和@Configuration是有区别...
@configuration和@component之间的区别
cj_0513的博客
05-29 363
@configuration和@component之间的区别是:@Component注解的范围最广,所有类都可以注解,但是@Configuration注解一般注解在这样的类上:这个类里面有@Value注解的成员变量和@Bean注解的方法,就是一个配置类。 @component多例的,@configuration是单例的 ...
@Configuration 和 @Component区别
qq_42506750的博客
04-22 722
被。
@Configuration 注解源码分析
09-17
@Configuration注解的源码分析如下: 1. @Configuration注解是一个元注解,它本身被@Configuration元注解标注。这表示@Configuration注解本身是一个配置类,用于配置其他的配置类。 2. @Configuration注解是一个@...
写文章

热门文章

  • 惠普光影精灵5 拆机与配置升级教程 77036
  • SpringBoot 事务作用于异步方法或线程池踩过的坑 7238
  • springboot + @Async 实现异步方法之踩坑填坑 7225
  • Secure CRT 本地文件上传至远程服务器 5866
  • Could not find symbol “gHotSpotVMTypes“ ... Can‘t attach the process:ptrace(PTRACE_ATTACH) ... 5741

分类专栏

  • spring 11篇
  • spring boot 10篇
  • Apollo 2篇
  • sentinel 1篇
  • docker 4篇
  • git 1篇
  • Spring Cloud 1篇
  • Hystrix Dashboard 1篇
  • 跨域 1篇
  • 笔记
  • ELK 3篇
  • Java 3篇
  • Kafka 1篇
  • redis 2篇
  • 并发编程 1篇
  • mybatis 4篇
  • spring mvc 1篇
  • Linux 1篇

最新评论

  • python 比较 mysql 表结构差异

    CSDN-Ada助手: 不知道 MySQL入门 技能树是否可以帮到你:https://edu.csdn.net/skill/mysql?utm_source=AI_act_mysql

  • sentinel-dashboard-1.8.0.jar 下载及自定义持久化

    ༺鲸落༻: 感谢雷锋

  • sentinel-dashboard-1.8.0.jar 下载及自定义持久化

    Francis Einscan: java -jar执行就行

  • sentinel-dashboard-1.8.0.jar 下载及自定义持久化

    hu-277: 这个sentinel-dashboard-nacos.jar怎么启动啊,我为什么启动失败

  • 惠普光影精灵5 拆机与配置升级教程

    2301_76293595: 我的只能换不能加,电脑没有内存了,选了一个980

大家在看

  • 【无人机姿态控制】基于matlab反步控制方法无人机姿态控制和轨迹跟踪控制(位置误差 偏航角 控制力矩)【含Matlab源码 4585期】 641
  • P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布 225
  • 无人机集群路径规划:蜣螂优化算法( Dung beetle optimizer, DBO)求解无人机集群路径规划,提供MATLAB代码
  • 初识扫雷! 314
  • 基于51单片机wifi智能大棚环境监测控制液晶显示设计 1629

最新文章

  • python 比较 mysql 表结构差异
  • Apollo 整合 Spring Boot 原理分析
  • 一张图搞懂Spring Boot内嵌Tomcat原理
2024年1篇
2021年5篇
2020年33篇
2019年13篇

目录

目录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值

玻璃钢生产厂家金华玻璃钢陶瓷雕塑企业果洛玻璃钢雕塑造型陕西景区玻璃钢雕塑批发泰安玻璃钢雕塑定制商场美陈公司 厦门古城区玻璃钢雕塑广州天河玻璃钢卡通雕塑山西个性化玻璃钢雕塑订做价格商场美陈图片大全文字沈阳细致玻璃钢座椅雕塑2017年商场美陈展江苏农场迎宾玻璃钢雕塑天津定制玻璃钢雕塑方法楼盘玻璃钢雕塑怎么样云南玻璃钢动物雕塑揭阳楼盘玻璃钢人物雕塑校园不锈钢玻璃钢人物雕塑设计曲阳玻璃钢桃子雕塑苏州玻璃钢雕塑加工厂佳木斯玻璃钢雕塑定制焦作仿铜玻璃钢雕塑生产厂家南岗玻璃钢雕塑定做福建玻璃钢孔子雕像雕塑加工淮北玻璃钢雕塑哪家好玻璃钢牛雕塑工厂玻璃钢喷泉雕塑视频姜太公钓鱼玻璃钢雕塑价格郑州人物玻璃钢雕塑优势昌平商场门头美陈装饰江苏优质玻璃钢雕塑销售厂家香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化