springboot自动装配源码分析

        最近,重新学习了springboot2的相关内容,对于springboot的相关源码进行的简单的重新学习,所以就想在这里给大家分享一下我自己的学习理解,也算是做一个笔记。

        注意:我的springboot版本是2.7.3,不同版本代码可以不太一样,但是操作一样的(大版本不变的情况下)。

 

目录

第一步,创建新工程

第二步,分析@springbootApplication注解

@springbootConfiguration

@Configuration注解

@indexed

@EnableAutoConfiguration

@AutoConfigurationPackage

@Import({AutoConfigurationImportSelector.class})

第三步,总结         

最后关于springboot学习的建议


第一步,创建新工程

        新建一个新的springboot空项目

 

 因为我们这里创建的空工程,所以不用额外添加任何依赖

 

这样我们的空工程就创建完成了

第二步,分析@springbootApplication注解

我们打开@springbootApplication注解

 

@springbootConfiguration

 

@Configuration注解

        相信在spring中学的过的同学们都应该知道这个注解的作用是啥,如果没有学习过spring的同学,还是建议先学习完ssm(spring,springmvc,mybatis)框架,再来学习springboot。

        @Component注解的作用就是将类放进spring容器,让spring容器为此类创建实例对象。

@indexed

        此注解没有过多的作用,主要作用是加快加载速度,是利用的反射原理

@EnableAutoConfiguration

我们先打开@EnableAutoConfiguration注解

@AutoConfigurationPackage

        在这里说一下@Import注解,此注解是引入某一个类,这个类会被加载进spring容器中,就可以使用了

 

         在这里我们需要弄清metadata和registry这两个参数是干嘛的,所以我们在这里打上断点,debug一下

         我们可以看到metadata这个形参是的值是com.nice.springbootDemoApplication这个引导类,registry的值是BeanDefinitionRegistry,是一个注册Bean的类。

        然后我们研究传进register方法的参数都是什么? registry和(String[])(new AutoConfigurationPackages .PackageImports (metadata)) . getPackageNames().toArray(new String[0]),registry参数上面已经知道,那后面这一大串的东西都是什么呢?首先这个参数是一个String类型的数组,所以我们能知道,这个只是一堆字符串而已,并没有特别的对象和方法。我们继续往后看,PackageImports ()方法的作用是包导入,传入的参数是metadata,我们可以知道是将com.nice.springbootDemoApplication引导类所在的包导入,又可以说是将这个包扫描。后面的方法就是将获取的包名转化为String类型的字符串传入。

         然后我们点入register方法中,我们可以看到register方法先对registry进行了一次逻辑判断,如果是true就怎么怎么样,如果是false就怎么怎么样。我们先不管逻辑判断的情况,我们先观察这两种情况执行的代码之间的差异。我们能看到如果返回的false,程序会注册一个BeanDefinition,然后我们点进BasePackagesBeanDefinition方法一探究竟。

        我们看到addBasePackages方法出现在逻辑判断返回值为true的执行代码之中。那我们就知道了逻辑判断是否成功,最终都会执行这个addBasePackages方法,我们再把两种情况的代码的差异拿出来看看,从中我们能知道逻辑判断的对错情况,执行代码的差别只有new了一个Auto ConfigurationPackages对象,然后我们再来看看逻辑判断到底是判断的什么?

        我们找到SimpleBeanDefinitionRegistry包中的方法实现。我们可以发现此逻辑判断是确定registry注册表中是否存在枚举类BEAN所定义的值。

        所以register方法的研究就彻底完成了,此方法先判断registry对象中是否包含BEAN(AutoConfigurationPackages.class.getName():自动配置包的名称),如果没有我们就在返回值为false的代码中new一个AutoConfigurationPackages,然后对AutoConfigurationPackages对象进行基础设置后将其加入包扫描中。如果存在AutoConfigurationPackages类那么就直接添加进包扫描中。

@Import({AutoConfigurationImportSelector.class})

         我们点进AutoConfigurationImportSelector.class

         我们发现AutoConfigurationImportSelector类实现了DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered六个接口,我们观察接口发现,这六个接口可以分成三类,一类是DeferredImportSelector ,第二类是以Aware结尾的BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware,第三类是Ordered。让我们由简到难来分析这三类接口。

        第三类接口(Ordered),我们点进ordered接口发现,接口结构非常简单,只定义了最高优先级、最低优先级和getOrder()方法。

         优先级很好理解,就不过多解释了,我们点开getOrder方法找到AutoConfigurationImport Selector实现类中的getOrde()方法。

 

         通过观察得知:getOrder()方法,返回的优先级是最高优先级-1,由此接口我们可以知道,类的加载是由顺序的,为什么有顺序?我们假设一共有20个类需要加载,那么如果第10个类的加载依赖第20个类,那么如果第20个类加载在第10个类的后面,那么第10个类的加载是失败的,所以第20个类就必须加载在第10个类的前面。(PS:关于类的加载依赖有十几种规则,如果有不懂的,可以去学习一下。)

        第二类接口,以Aware结尾的BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware接口。实现此类接口的Bean可以在此环境中使用Aware前面的对象。(在此无需过多关注此类接口)

         第三类接口(重点),DeferredImportSelector接口。此接口实现ImportSelector接口,此接口中有selectImports方法,此方法会在process方法执行后执行

        我们先来看看process方法,方法的第一段代码是一个断言机制,我们可以不看它,我们专注与核心代码,看第二段代码。第二段代码的核心方法就是getAutoConfigurationEntry()

        我们点开getAutoConfigurationEntry()方法

         我们可以看到getAutoConfigurationEntry()中就是一次逻辑判断,那么我们就看看逻辑判断的条件,(!this.isEnabled(annotationMetadata))此逻辑判断方法是判断springboot引导类上是否存在@springbootApplication注解,如果不存在,则返回EMPTY_ENTRY(空目录),如果存在,则开始读取@springbootApplication注释中的属性

        读取了@springbootApplication注释中的属性,开始读取候选配置

         我们已经将spring工厂加载需要的工厂类型名称解析出来,而且确保spring工厂的加载类存在,然后我们点入loadSpringFactories将spring工厂加载需要的工厂类型名称和spring工厂的加载类传入。我们现在需要确认loadSpringFactories如何将所需类加载出来,所以我们进去loadSpring Factories方法。

         因此我们知道了,自动转给最终会读取从一个叫“META-INF/spring.factorites”的文件中读取需要配置的候选配置。那么最后一个问题META-INF/spring.factorites在哪呢?

        我们在加载jar包的地方按ctrl+F,搜索spring-boot找到有autoConfiguration的包。

         最后我们来看看META-INF/spring.factorites文件中定义的配置

第三步,总结         

        好了,我们关于springboot中关于自动装配的源码分析就到这里啦,这是我第一次写这样的文章,所以难免在部分细节处分析的不到位,或者我是依靠自己的思维在讲这部分的源码,可能会存在部分同学们会在阅读过程中存在困惑,所以我这篇文章有什么不足之处,还请各位大佬同学们不吝赐教,在评论区告诉我吧。

最后关于springboot学习的建议

        因为我还在一名在校的大一学生(开学大二),所以涉及专业课的部分都没学习过,只是简单的学习过计算机导论和c语言。关于Java的学习,我还是在B大上找的资源,在自己课余的时间里学习的,所以我在自学springboot这门技术上还是有一点发言权(doge狗头保命)。

        关于springboot的学习,“B大”上面的资源太多太多,对于新手自学来说,很难自己分辨优劣。我自己的话,我是搜了几大培训机构的课程再看,我最开始看的是“尚大”的springboot2,我个人感觉,“尚大”的springboot2非常不适合新手学习,它更像是一个进阶的springboot2,他比较适合有过一定springboot项目开发经验的老手去学习,去进阶。当然如果你的目标是大厂的话,我还是非常建议能在做完两三个基础项目的前提下,将自己springboot的水平进阶一下。其次,我看了“某马”的springboot2教程,我个人感觉这门课还是非常适合新手学习springboot的同学们的,我在一知半解的看完“尚大”的课程后,是找了一个非常基础的项目做完之后,才再次学习“某马”的springboot。

        我个人呢还是比较建议大家先学习“某马”的springboot课程,在做两三个项目再看一遍“尚大”最新的springboot2教程。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值