觉得无从下手?一步一步来。有些路,走不通了,就先放一放。去其它路上转转,可能一会儿回来又可以走通了。
我们先走第一条路。Spring Boot应用启动是在main方法里调用SpringApplication的run方法,所以内置Tomcat启动流程一定在包含在其中。我们可以debug,但在我们不知道任何有用信息的情况下,尤其是Spring的调用链一般都很深,所以一步一步的debug非常难。这条路走不通,我们先走其他条路。
如果你认真观察,你会发现Spring Boot应用启动日志里有这么几句,看下图
这几句话都跟Tomcat有关。我们先看第一个箭头指向的日志输出,该日志是有TomcatWebServer打印的。我们通过集成工具(我假设你用的也是IDEA),Double Shift然后输入TomcatWebServer,然后Ctrl+F输入initialized关键字,我们找到打印这条日志的代码行,看下图
我在该行加了断点,目的是让我们可以跟踪下调用链。我们重新debug启动,看下图
我们看到一些熟悉的东西--refresh方法,onRefresh方法。onFefresh方法的作用是初始化特定上下文子类中的其他特殊bean。在这里,AbstractApplicationContext的特定子类指的是ServletWebServerApplicationContext。这个类的的onRefresh方法中创建了Tomcat,看下图
WebServer是通过ServletWebServerFactory创建的。通过上图,我们可以看到此时ServletWebServerFactory的实例是TomcatServletWebServerFactory。为什么是Tomcat呢,而不是Jetty或者Undertow,我们现在不得而知。但我们可以猜测,是因为我们的类路径下有tomcat-embedded.jar。
我们先不管为什么是Tomcat,我们知道已经是Tomcat。那我们来具体看看,是如何初始化TomcatWebServer的。在我们看这个问题之前,我们得先看如何构造Tomcat,因为TomcatWebServer内部持有一个Tomcat的引用。Tomcat跟TomcatWebServer是什么关系呢?大概就相当于程序和进程的关系吧!