赞
踩
首先肯定是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里就已经包含了这个启动类对象了。
然后往下走,refreshContext刷新容器的方法。跟进去一直跟到super.refresh(),如下图的这个位置,这部分就属于spring的内容了。
然后跟进去到达下图:这个方法才是核心
跟进去跟到下图这块
所以在上图的for循环中循环到第6个字符串(图中下标为5)的时候,也就是启动类 springbootStudyApplication的时候看一下会发生什么事情。
当循环到springbootStudyApplication的时候进入了else if
configCandidates.add configCandidates是一个集合,在这个方法第一行就定义了。
然后还是这个方法,继续下一步跳过,一直走到下图这里:注意这个注释,解析每一个加了@Configuration注解的类。启动类里是有加这个注解把,把启动类上面的注解点进去就会发现注解里面的注解有@Configuration注解
跟一下上图的new对象的构造方法。下图就是构造方法,可以看到构造方法里有包扫描的解析,有条件判断的解析
继续往下走
往下走
然后往下跟,把断点打在这个类的这一行
debug这个可以看到ann 就是启动类上面的SpringBootApplication注解
到此为止,这里面就完成一件事:启动类里面是否包含注解,如果不包含注解。
到此为止的调用链是这样子,以防下次找不到先截图出来:
然后往回返到这里:可以看到sourceClass有值,看这个dowhile循环
跟进do里的这一行代码,到这里:解析启动类所在的根目录下的组件。例如com.xy下的所有子包里的组件
继续往下走:看这个注释就知道什么意思了,该处理import注解了
那么启动类上的注解的注解里,包含几个import注解呢?
那么代码继续往下走:跟进去
这一行代码是怎么执行,肯定是先执行最外层的processImport,里面的第三个参数是一个方法getImports(),记住我说的话,然后跟进processImport
发现第三个参数的size = 2 ,那也就是说getImports方法的返回值是2,而这两个值刚好是启动类里import的类。
那么看一下getImports这个方法,很有趣,是采用递归调用的方式
当循环递归调用完毕后,结果是:
好了到此为止,说的差不多了,那么下来就是完整的流程:127个类。这个有的版本是124个类,不同版本的springboot这里自动装配的个数会有细微的差异
先是prepareContext(预准备容器)的时候加载启动类,在refresh(刷新容器)的时候加载启动类注解以及该注解里的各种子注解,最重要的是加载 Import 注解,而import注解里倒了几个类,在getCandidateConfigurations方法处打一个断点就可以看一下是如何加载的了。
Candidate这个单词的意思是:被候选的,认定的
@Conditional:自动配置类在一定条件下才能生效
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。