springboot 聚合模块启动 找不到或无法加载主类_SpringBoot自动装配原理

v2-4bc9ab5cdbdf616eb23b14e3bbb321a1_b.jpg

首先肯定是main方法了,但是main方法上有注解,有人就说了,点进去,然后再点进去,会看到xxx注解,import了一个xxx类。然后加载了spring.factory,然后注入那些key对应的value的类

话是这么说不错,但是这不对。这个类看一下肯定是先运行main方法里的run方法啊,咋可能不运行main方法就开始读注解呢?所以一定是先运行main方法里的run方法,到一定的步骤的时候,才加载main方法上的@SpringBootApplication注解。

所以下来就看一下SpringBoot的自动装配这一步步是如何进行的。

main方法这个类也是一个component,也是需要注入的,那么也是需要往context里注入的,同时也要扫描注解,拿到选择器。


prepareContext 这个方法的 load 方法 里加载包含main方法的主类SpringbootStudyApplication,所以在当前context里就已经包含了这个启动类对象了。

v2-d697aafc26b823f87e9661c5f6c9f05f_b.jpg

然后往下走,refreshContext刷新容器的方法。跟进去一直跟到super.refresh(),如下图的这个位置,这部分就属于spring的内容了。

v2-bc61ced6fd68d2d347615f2b4f779e41_b.jpg

然后跟进去到达下图:这个方法才是核心

v2-4c29a4f465b8c6dfe220d62cb9e325f9_b.jpg

跟进去跟到下图这块

v2-154eb932da4e071064333f6b64b50e01_b.jpg

v2-df3160f3f5d7a7a4baea718c93f94049_b.jpg

所以在上图的for循环中循环到第6个字符串(图中下标为5)的时候,也就是启动类 springbootStudyApplication的时候看一下会发生什么事情。

当循环到springbootStudyApplication的时候进入了else if

configCandidates.add configCandidates是一个集合,在这个方法第一行就定义了。

v2-3564add8cf0bc13668d63d7c60361d9f_b.jpg

然后还是这个方法,继续下一步跳过,一直走到下图这里:注意这个注释,解析每一个加了@Configuration注解的类。启动类里是有加这个注解把,把启动类上面的注解点进去就会发现注解里面的注解有@Configuration注解

v2-c932aea3f04a35fb0518d5654653eefa_b.jpg

跟一下上图的new对象的构造方法。下图就是构造方法,可以看到构造方法里有包扫描的解析,有条件判断的解析

v2-08a256717bea4932e265c63d55bfaf64_b.jpg

继续往下走

v2-5ee398512b7757520280338aee75d994_b.jpg

往下走

v2-9f793206eb3ad30145ef05e9622052c4_b.jpg

然后往下跟,把断点打在这个类的这一行

v2-617f88b01fab884c0a9616e696108871_b.jpg

debug这个可以看到ann 就是启动类上面的SpringBootApplication注解

v2-8245363d12bf0fd4b4911c5c900cef9a_b.jpg

到此为止,这里面就完成一件事:启动类里面是否包含注解,如果不包含注解。

到此为止的调用链是这样子,以防下次找不到先截图出来:

v2-3fa2882e9e2bcf92326072815513a2a8_b.jpg

然后往回返到这里:可以看到sourceClass有值,看这个dowhile循环

v2-e4008dabf23e3049723b488011f544a6_b.jpg

跟进do里的这一行代码,到这里:解析启动类所在的根目录下的组件。例如com.xy下的所有子包里的组件

v2-cc46bd8097c874c6bfe61373071f34f0_b.jpg

继续往下走:看这个注释就知道什么意思了,该处理import注解了

v2-8da707582759b74b6d642e0e412571c3_b.jpg

那么启动类上的注解的注解里,包含几个import注解呢?

v2-01d1711b45541e61eed0e329aa66b842_b.jpg

v2-6180938067fb15cd3919f034e32690df_b.jpg

那么代码继续往下走:跟进去

v2-0ccfe42b6e8e3318287a6122f8044d02_b.jpg

这一行代码是怎么执行,肯定是先执行最外层的processImport,里面的第三个参数是一个方法getImports(),记住我说的话,然后跟进processImport

v2-8a69f7263d5a9901a9be60e2b893427c_b.jpg

发现第三个参数的size = 2 ,那也就是说getImports方法的返回值是2,而这两个值刚好是启动类里import的类。

那么看一下getImports这个方法,很有趣,是采用递归调用的方式

v2-32ecf604c70d20380faa452992060542_b.jpg

v2-670a7b90d6228f78cde358496ce108ff_b.jpg

当循环递归调用完毕后,结果是:

v2-fa614098bcc0cf5460f9dd7f1d185574_b.jpg

好了到此为止,说的差不多了,那么下来就是完整的流程:127个类。这个有的版本是124个类,不同版本的springboot这里自动装配的个数会有细微的差异

v2-d4697fe34645bb84140aeb7f0f5f68db_b.jpg

先是prepareContext(预准备容器)的时候加载启动类,在refresh(刷新容器)的时候加载启动类注解以及该注解里的各种子注解,最重要的是加载 Import 注解,而import注解里倒了几个类,在getCandidateConfigurations方法处打一个断点就可以看一下是如何加载的了。

Candidate这个单词的意思是:被候选的,认定的

@Conditional:自动配置类在一定条件下才能生效

v2-26e2a98051d28de9c1d9a9fedce0a5f3_b.jpg
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值