背景
我们目前大多数的公司都已经基于SpringBoot开发,SpringBoot确实给我们解放了生产力,但是我们是否应该好好研究一下它的加载机制,以及相关的自动加载的一些流程,SpringBoot到底是如何进行相关地启动加载工作的。另外的其实很多公司面试的时候也是比较喜欢问一下SpringBoot的启动流程,所以,我们就从源码入手,对其好好研究一下。我们就从一步一步debug代码来进行分析吧。
创建一个简单工程
我们就比较简单地通过Spring Initializr的方式创建一个工程,如下图,当然我们也可以直接在相关的官网上进行创建基础demo,然后将其下载下来,官网地址:https://start.spring.io/

为了后面能够更好地查看容器类型的源码,我们让springboot支持web,我们添加如下pom依赖:
1 2 3 4
| <dependency> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-webartifactId> dependency>
|
我们找到对应的应用程序的入口,并且给其入口打上断点,如下图

按住F7(本人的是mac,直接按住fn+f7)进入断点,我们先看到进入run方法之后如下:
1 2 3 4 5 6 7
| public static ConfigurableApplicationContext run(Class> primarySource, String... args) { return run(new Class[]{primarySource}, args); }
public static ConfigurableApplicationContext run(Class>[] primarySources, String[] args) { return (new SpringApplication(primarySources)).run(args); }
|
走到这步之后,直接进入其对应的SpringApplication的构造函数,我们看看SpringApplication构造器里面做了哪些东西:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) { this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = new LinkedHashSet(Arrays.asList(primarySources)); this.webApplicationType = WebApplicationType.deduceFromClasspath(); this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class)); this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = this.deduceMainApplicationClass(); }
|
接下来我们先看一下获取web应用程序类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| private static final String[] SERVLET_INDICATOR_CLASSES = new String[]{"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"};
static WebApplicationType deduceFromClasspath() { if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) { return REACTIVE; } else { String[] var0 = SERVLET_INDICATOR_CLASSES; int var1 = var0.length;
for(int var2 = 0; var2 < var1; ++var2) { String className = var0[var2]; if (!ClassUtils.isPresent(className, (ClassLoader)null)) { return NONE; } } return SERVLET; } }
|
由于我们一开始即成了web的maven依赖,所以当前debug下来,返回给我们的是servlet容器。
从源码中我们可以看出其实web的应用程序有三种,分别如下:
1 2 3
| NONE, SERVLET, REACTIVE;
|
上述提到webflux(说实话,还没仔细研究,官网意思大概是这样的Spring WebFlux 是一套全新的 Reactive Web 栈技术,实现完全非阻塞),后面打算专门出一篇文章去研究一下。
拿到类型之后继而初始化应用上下文。具体debug进去看一下源代码: