正文:本篇博客旨在和网友们交流技术,无“针锋相对”一说。本人目前菜鸟实习生一枚,知识能力浅薄,以下所写难免有疏漏之处,
若有不恰之处,烦请各位指点。
流程我们先来思考一个问题:想必大家一定都经历过SSM的那一堆令人抓狂的配置文件,使用SSM初始化一个项目的时候我们总是要先整合一堆配置文件然后才能真正的去写业务代码。而Springboot的出现让我们不用再去写那一堆墨守成规的配置文件这极大节约了我们构建项目的时间,但是大家有没有想过,即使Springboot已经很方便了,但它仍保留了一个配置文件(application.properties或application.yml文件),我们在此文件中配置一些常用的信息,如项目端口,项目路径等等,那Springboot是如何读取这些配置项的呢?其实就可以由此为切入点来探究Springboot的自动配置流程,接下来我将具体一步步深入。
对于application.yml来说,在我们眼中看来也只是一堆光秃秃的配置文件,想要分析它们我们还是得回到最初学Springboot的时候最先接触到的一个类。没错,就是每个Springboot的项目都会有的一个启动类,而且每个启动类上面都会有一个@SpringBootApplication注解,像这样:
我们可以由此注解入手,来剖析在项目启动的过程中,Springboot是如何一步步进行自动装配的。
点进该注解后,我们会看到以下几个注解:
白色部分:
这些注解都是我们接触的比较多的注解,大家都比较熟悉,我在这里简要回顾以下便不再赘述。 @Target :来标注注解的作用范围,像本例中的TYPE可以用来声明类、接口、注解等等。 @Rention:是用来标注该注解的生命周期,本例中的RUNTIME就代表,被修饰的注解只在运行时有效。 @Document:被修饰的注解,可以用javadoc进行记录 @Inherited:强调继承的效果。 @SpringBootConfiguration:标注当前类是配置类 @ComponentScan:这个大家都比较熟悉了,组件扫描器。来扫描一些包将包内的bean交给容器来管理
红色部分:
@EnableAutoConfiguration: 我用红框圈出的部分大概意思就是:此注解可以使整个环境自动配置生效。 划线部分:其实这点我不太懂啥意思,总感觉是“如果你内嵌了tomcat的jar包,spring就会自动帮你配置关于tomcat的一些配置”,这点我们先不追究,不太影响后面的分析。深入
继续点进@EnableAutoConfiguration,可以看到如下几个注解:
白色部分多了一个@AutoConfigurationPackage,此注解的大致作用和@ComponentScan差不多,有兴趣的小伙伴可以去了解一下它们的差别。
接下来我们重点关注红色部分里的@Import({AutoConfigurationImportSelector.class)
@Import({AutoConfigurationImportSelector.class}) :
@Import({AutoConfigurationImportSelector.class})这行代码的作用就是引入AutoConfigurationImportSelector这个类,我们层层深挖现在终于碰到了一个和自动配置相关的类(藏得可真够深的),分析到这一步,所有的谜底都在这个类里面,让我们再点进去这个类里面看看到底都有些什么才支撑了SpringBoot的自动装配的能力。
探究点进去一看:“woc,怎么这么多方法,我该从哪块入手”
不急我们慢慢分析,只要找到正确的方法,我们就成功一半了。
接下来的分析可能会有些枯燥,但是跟着一步步走,很容易就能明白这个过程。废话不多说,我们继续往下捋。在上图圈出的那一堆方法中,有一个和自动配置相关的方法(从名字上就能猜个差不多),现在我把这个方法贴在下面。
没错,就是getAutoConfigurationEntry()方法,现在我们去看一下这个方法的内部逻辑
老规矩,我又圈出来了红白两部分,不过这次我们先不关注白色框框,而是先顺着红框往下深挖。可以看到红框内调用了本类中的一个getCandidateConfigurations(形参)方法,这个方法的字面意思是:获取候选的配置,继续点进此方法内部,可以看见如下:
这里面有个断言,英文的大意就是“找不到spring.factories文件”到这一步我想大家应该都明白了这个方法的用途了,就是此方法会加载spring.factories文件,现在我们就找找这个文件看看它里面到此藏了啥,使用IDEA中的当前类定位按钮来进行查找,步骤如下:
然后往上划可看到如下:
至此为止,我们终于找到了一个底部的文件,现在让我们看看里面都有啥:
spring.factories:
可以看到,spring.factories都是一组组的key-value形式的内容,图中红色部分就是一个全类名为EnableAutoConfiguration的key,而它的value就比较牛逼了,是一个全部以AutoConfiguration结尾的列表,中间以逗号分格,其实getCandidateConfigurations(形参)中的SpringFactoriesLoader.loadFactoryNames()方法就是取到该文件下的一系列类名,随后将这些类自动加载至IOC容器中,从而达到自动配置的。思考
这些配置类(大概有130多个)难道都要被容器加载完吗,不急,我们回头看,把上面的那几个方法debug一下,就可以得到我们想要的信息了。
项目启动后,先是走到了我在getAutoConfiguration()方法中打的端点,此时程序走到此处,List集合仍是空的,我们继续点击,让程序调用getCandidateConfigurations()方法,见下方:
我们看到,当getCandidateConfigurations()方法执行完的时候,List集合中的元素数量是134,此时继续让程序往下走,会把这134返回到getAutoConfiguration()中,如下;
现在程序走到了这一步,大家还记得我在上图中圈出的那个白色框吗,我当时还留了个悬念,没有解释白色框的作用,现在程序其实就已经走到白色框里面了,大家应该能猜出来,其实这个白色框中的代码就是来筛选、过滤一些不符合条件的自动配置类的,我们先让程序走完,看到最后还会剩下多少配置类,然后我们在分析是如何去除掉这些配置类的。
明显看到,最后只剩下了43个配置类
解释不装配的情况如下几种:
-
手动排除:
-
通过@ConditionOnBean注解来判断
,最后只剩下了43个配置类**
解释不装配的情况如下几种:
-
手动排除:
[外链图片转存中…(img-5s2fzIzu-1658296959810)]
-
通过@ConditionOnBean注解来判断
注释:由于时间问题(目前正在实习)本篇文章还没有形成闭环,我下次会补充一下@ConditionOnBean的讲解,并把它和配置文件联系起来,因为我们博客的开头是从配置文件入手的,所以本篇仍未完全形成闭环,迫于时间原因,只能暂时先写到此处,抽空我会把剩余的部分补上。



