我们都知道SpringBoot自问世以来,一直有一个响亮的口号“约定优于配置”,其实一种按约定编程的软件设计范式,目的在于减少软件开发人员在工作中的各种繁琐的配置,我们都知道传统的SSM框架的组合,会伴随着大量的繁琐的配置,稍有不慎,就可能各种bug,被人发现还以为我们技术很菜。而SpringBoot的出现不仅大大提高了开发人员的效率,还能避免由于“手抖”带来的配置错误。
很多程序员都感慨SpringBoot的到来大大解放了生产力,但是也有聪明的程序猿会多思考一下下,SpringBoot是怎么做到约定的配置?它配置在了哪里?又是怎么启动的等等一系列的问题。今天咱们就来一起跟随源码探究下SpringBoot到底是如何做到“约定优于配置”的。
首先,我们先介绍下我们演示的项目环境,我们先使用Spring Initializr来创建一个SpirngBoot工程。我们使用的版本是SpringBoot 2.1.5.RELEASE。

接下来就只在pom.xml文件中添加一个web工程的依赖,是为了观察后面容器类型的源码。

这样我们的环境就准备好了。
我们跟着SpringBoot的源码来探究它的启动流程,首先,先找到这个应用程序的入口主方法,在上面打一个断点。





这里有两个加载配置类的地方其实都指向了META-INF/spring.factories,通过断点我们可以看到应用程序是加载了以下几个jar下的spring.factores文件。
双击Shift搜索spring.factories可以看到它存在于以下工程中

spring-boot-2.1.5.RELEASE.jar下的spring.factores(截图未完整截取)

spring-boot-autoconfigure-2.1.5.RELEASE.jar下的spring.factores

从Map中根据org.springframework.context.ApplicationContextInitializer的类型拿到需要的类初始化类,断点进入getOrDefault(factoryClassName, Collections.emptyList());方法

之后就是把加载到的需要初始化的类进行实例化添加到一个集合中等待备用

三、初始化监听器类
最关键的的还是这句

当我们跟进去之后,会发现在初始化监听类的时候和上面初始化应用上下文是一样的代码。唯一不同的是getSpringFactoriesInstances(ApplicationListener.class))传进去的是•ApplicationListener.class所以这里就不再赘述。
四、推演主程序类
也就是这个最关键的代码了
this.mainApplicationClass = deduceMainApplicationClass();


到这里就完成了SpringBoot启动过程中初始化SpringApplication的过程。
小结
这篇文章主要是给大家说了下SpringBoot启动过程中初始化SpringApplication的流程,大致可以分为四个步骤:
1. 推演web应用的类型(如果没有加web依赖类型NONE)
2. 初始化ApplicationContextInitializer
3. 初始化ApplicationListener
4. 推演出主程序类
通过这样四个步骤就完成了第一步SpringApplication的初始化过程。
怎么样,你了解了么?欢迎和我们一起探讨。
更多IT技术干货,请关注课工场,和我们一起关注前沿技术,快速提升。
网友评论