Springboot 自动装配原理探索

官网介绍

先来看看官网是怎么定义这个自动装配的~

可以看到这里说,当你引入了某个 jar 依赖包时,Springboot 会尝试根据这个依赖去自动配置 Spring 应用程序。

而且这里还说明了,你应该在 一个配置类 @Configuration 上选择 @EnableAutoConfiguration 和 @SpringBootApplication 这其中的一个注解,来让自动配置生效.

那么,知道这些信息后,我们就开始愉快地看源码环节了~ 冲冲冲!

对了,探索的 Springboot 版本为 2.4.5

@SpringBootApplication

来到 @SpringBootApplication 注解中,可以发现它是一个组合注解,除了前面四个基本的元注解外,还有下面这三个 @SpringBootConfiguration , @EnableAutoConfiguration ,@ComponentScan

源码如图

@SpringBootConfiguration

我们先来看这第一个注解,如图,可以发现它其实是一个 @Configuration 注解,@Configuration 注解的作用是将其作为一个配置类,来配置 Spring 的上下文,相当于 Spring 的 XML 配置文件中的 <beans>

源码如图

@ComponentScan

这个的作用就是 扫描指定路径下的组件,并加入到 IOC 容器 中,相当于Spring 的 XML 配置文件中的 <context:component-scan/>

源码如图

可以发现它里面有一个 @Repeatable(ComponentScans.class) 注解,表示可重复使用@ComponentScan 注解

注意,这里会按照我们自定义的方式去排除一些类,具体是通过实现 TypeFilter 接口并重写 match 方法来实现 。

小细节

这里还有个点要注意下~

AutoConfigurationExcludeFilter 会检查配置类,如果该配置类和 META-INF/spring.factories 文件中的 EnableAutoConfiguration 对应的配置类一样的话,会被排除掉~

@EnableAutoConfiguration

终于,来到本文的重点了

看到它的名字就知道它就是这个 自动配置 的主角了

源码如图

可以发现它是一个组合注解

先来看看这个注解1 @AutoConfigurationPackage

@AutoConfigurationPackage

从名字就可以看出它是一个 自动配置包路径 的注解

源码如图

从这段注释我们可以发现,当没有配置这个 basePackages 或者 basePackageClasses 时,这个类就会自动将该注解所在的包作为基本路径进行注册

接着,我们再来看看这个框框里的内容~ @Import(
AutoConfigurationPackages.Registrar.class)

@Import

先来看看这个注解的作用吧

源码如图

可以发现它的作用也很简单,就是导入组件,比如常见的 @Configuration 类或者ImportSelector 和
ImportBeanDefinitionRegistrar 的实现类,或者其他一些常规的组件如 @Component ,@Service 等等

Registrar

继续看看这个 @Import(
AutoConfigurationPackages.Registrar.class) ,可以发现该注解导入的是 Registrar 类 , 那么我们继续探索下,看看它干了什么~

源码如图

从该类的注解可以看出,它的作用是通过
ImportBeanDefinitionRegistrar **来保存这个基本包的路径的 **


那么,讲完第一点 ,我们简单了解到这个 @AutoConfigurationPackage 就是用来配置基本包 ,我们接着再来看看第二点,这个 @Import(
AutoConfigurationImportSelector.class) 注解。

我们可以发现它导入了
AutoConfigurationImportSelector 类。

AutoConfigurationImportSelector

看这个名称,可以大概知道它是一个 组件选择器

关键步骤介绍

process

这个方法在获取这些 Import 类时会被调用,具体可以看结尾的流程图~

getAutoConfigurationEntry

获取自动配置实体类 ,里面还有本文的重点~

getCandidateConfigurations

来到这里,可以发现它调用到这个 SpringFactoriesLoader ,这里就不得不提下这个 Springboot 的 SPI 机制了,另外它和我们上文(服务发现机制SPI居然是破坏者?! )中提到的 Java Spi 有什么不同呢 ?

再继续往下看一下~

Springboot SPI机制

老规矩,看一眼注释先 哈哈

spring.factories 文件

举个栗子

# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener

可以发现它加载的是 META-INF/spring.factories 这个文件 ,相比 java 的 META-INF/services ,有以下的不同点:

  1. 从名字上就可以发现很大的不同( 一个是 factories 文件,一个是以接口全名命名的文件 )。
  2. spring.factories 以一个聚合的作用,把相应的接口和实现类以 key = value 形式展现在 spring.factories 文件中。
  3. spring.factories 中的所有配置项会加载到我们的缓存中,以 Map<String,List<String>> 形式存储,但不是所有的都会被实例化,被加载到 IOC 容器中,除了必要的类外( EventPublishingRunListener 等 ),还有满足特定条件下的自动配置类会被加载到 IOC 容器中

满足特定条件 ☞ 比如有没有使用到这个依赖( pom 中的 starter)

自动配置类 ☞ 指以 AutoConfiguration 结尾的那些类

可以发现这种按需实现的机制比java的一股脑实现灵活多了~

实例解析

比如 这里从 spring.factories 文件中加载了130个自动配置类

但是实际使用中,经过过滤后只有这 30 个了

这里还根据 优先级 做了一些排序~

自动装配流程图

这里只摘了一些关键步骤~ ,具体流程太长了 ,得从 SpringApplication 源码中的 refreshContext(context); 这里就先不介绍啦,后面有时间再写一下分享下这个 [[Springboot源码的启动过程]]

同颜色的类名和方法块对应~

图中左下角的 processImports 方法,就是将这些自动配置类进行实例化,包括配置类里面的 @Import , @Bean 等 ,一步步加载到 Spring 的 IOC 容器中。

总结

一. Springboot 的自动装配很重要的一点就是,就是要在配置类上开启 @EnableAutoConfiguration 或者 @SpringBootApplication 注解,来让自动配置生效

二. 自动配置的核心是 Springboot 的 SPI 机制 ,以及组件选择器
AutoConfigurationImportSelector,具体是通过其中的 getAutoConfigurationEntry 方法来获取 SPI 中的自动配置类并进行过滤,最后通过 processImports 将配置类加载到 IOC 容器中,完成自动配置

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容

  • 前言 如果我们想要使用传统意义上的 Spring 应用,那么需要配置大量的 xml 文件才可以启动,而且随着项目的...
    小梁同学jxy阅读 292评论 1 0
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,529评论 28 53
  • 信任包括信任自己和信任他人 很多时候,很多事情,失败、遗憾、错过,源于不自信,不信任他人 觉得自己做不成,别人做不...
    吴氵晃阅读 6,186评论 4 8
  • 步骤:发微博01-导航栏内容 -> 发微博02-自定义TextView -> 发微博03-完善TextView和...
    dibadalu阅读 3,131评论 1 3
  • 回这一趟老家,心里多了两个疙瘩。第一是堂姐现在谈了一个有妇之夫,在她的语言中感觉,她不打算跟他有太长远的计划,这让...
    安九阅读 3,501评论 2 4