前言

当初学习SpringBoot框架的时候发现他只会扫描启动类所在包下和子包。最近刚好在学源码,想要探究为什么是默认扫描启动类所在包,而不是其他路径?我从run方法开始debug。SpringApplication的run方法可以找到SpringBoot的大致启动流程。
在这里插入图片描述

多的不说,SpringBoot实际上也是依托与Spring的。而注解扫描不可能会放在创建应用上下文阶段的,debug发现在createApplicationContext和prepareContext方法调用后IOC容器中并没有扫描到我们自己定义的bean。但是我们的主启动类被加载了。
在这里插入图片描述
进入refreshContext方法,发现实际上调用的是Spring框架中的refresh方法。refresh方法贯穿了整个Spring框架的启动过程,内容有点多我就不详细介绍了。想要了解的可以去学习一下Spring源码。我只会大致说一下内容。
在这里插入图片描述
值得注意的是,obtainFreshBeanFactory在Spring中确实是创建ioc容器的。不过SpringBoot在调用refresh方法前就以及创建了,所以SpringBoot是不会重新创建容器的,我在具体的实现打断点结果并没有进入断点。
在这里插入图片描述
其他的方法我就不详细介绍了,SpringBoot的扫描重点是在invokeBeanFactoryPostProcessors方法中。invokeBeanFactoryPostProcessors方法就是调用各个BeanFactoryPostProcessor,不过调用过程也分优先级,它是优先调用@PriorityOrdered注解和@Ordered修饰的处理器。其中有一个关键的类:ConfigurationClassPostProcessor。顾名思义,翻译过来就是配置类后置处理器。
在这里插入图片描述

==============================================================================在这里插入图片描述
ConfigurationClassPostProcessor类就是负责扫描标记了@Configuration等注解,这就是为什么它要被第一个调用。只有它被调用了才能扫描到注解导入的Bean。在processConfigBeanDefinitions中会调用ConfigurationClassParser类的parse方法对启动类进行解析。
在这里插入图片描述
启动类上带了SpringBootApplication注解,结果为true。在这里插入图片描述
进入parse方法后会调用processConfigurationClass处理配置类。SpringBoot做事的一般都是do开头的,所以直接进入doProcessConfigurationClass方法。
在这里插入图片描述
终于在doProcessConfigurationClass方法中见到了熟悉的东西。在方法中会判断类上是否有@CompomentScan注解,而SpringBootApplication是个组合注解,点进去查看实际上是由@CompomentScan组合来的。
在这里插入图片描述
在这里插入图片描述
在parse方法中会对这个@CompomentScan注解的信息进行解析,比如拿到我们要扫描的包路径,但是默认是没有路径的,那SpringBoot是怎么处理的呢?SpringBoot会默认以启动类所在包为路径调用doScan进行扫描。
在这里插入图片描述
实际上到这里大家应该都以及知道了。有了包路径接下来就是扫描所有的Bean并解析成BeanDefinition放入ioc容器的map中。其中findCandidateCompoments就是进行字符串拼接,将刚才的包路径拼接上+/**/*.class,扫描对应的Bean。在这里插入图片描述
在这里插入图片描述

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐