我们知道在java编程中,每个对象都是有生命周期的。
在tomcat中,由于所有的组件均存在初始化、启动、停止等生命周期方法,拥有生命周期管理的特性,所以Tomcat在设计的时候,基于生命周期管理抽象成了一个接口Lifecycle,而Server、Service、Container、Executor、Connector组件,都实现了该接口,从而具有了init、start、stop、destroy等生命周期中的方法。

先来看一张启动过程时序图,了解一下启动顺序:

Tomcat启动的入口类:
org.apache.catalina.startup.Bootstrap类的main()方法
main方法是整个tomcat启动时的入口。在main方法中,使用bootstrap.init()来初始化类加载器和创建Catalina实例,然后再启动Catalina线程。

bootstrap.init()方法,用于初始化容器,首先创建类加载器,然后通过反射创建Catalina实例:

然后在
Bootstrap类的main()方法再调用Bootstrap的load()方法,在load()方法中通过反射来调用Catalina的load()方法

Catalina的load()方法先去解析Tomcat的Server.xml配置文件,然后会去调用server的init()方法解析
server.xml配置文件
调用
server的init()方法

此处使用了模板方法设计模式,最终调用的是实现类org.apache.catalina.core.StandardServer的initInternal()方法,在该方法中又调用了Service的init()方法,并且是在for循环中调用的,也就验证了一个Server中可以多个Service

跟上面一样,调用service的init方法最终调用的是实现类org.apache.catalina.core.StandardService的initInternal()方法,在该方法中主要完成三件事:
1、初始化Engine
2、初始化Executor
3、初始化Connector

Engine和Executor的初始化代码,都是类似的,就是向下一级一级调用init方法,来初始化对应的组件,这里我们就不再继续跟踪了,我们接下来跟踪一下Connector的初始化代码。Connector并不是接口,本身就是一个实现类,所以它的init方法调用的就是
org.apache.catalina.connector.Connector类的initInternal()方法,在此方法中创建了CoyoteAdapter对象,用于将Request对象转换成ServletRequest对象,再调用容器来处理请求,最后调用ProtocolHandler的init方法

调用ProtocolHandler的init方法时,根据我们使用的http协议,最终调用的是实现类org.apache.coyote.http11.AbstractHttp11Protocol的init()方法,而其中又调用的是父类org.apache.coyote.AbstractProtocol的init()方法,在其中又调用了Endpoint的初始化方法

最终调用的是org.apache.tomcat.util.net.NioEndpoint的bind()方法,在其中开启Socket连接,并绑定监听的端口

至此,初始化
init流程就结束了。接下来我们再来看start流程,再次回到刚开始的Bootstrap的main方法中在
load()方法之后紧接着调用Bootstrap的start()方法

在Bootstrap的start()方法中,同样是利用反射调用Catalina的start()方法

在Catalina的start()方法中,又调用了Server的start()方法

在
Server的start()方法中循环调用了每个Service的start()方法,然后在Service的start()方法中做了三件事1、调用
Engine的start()方法2、调用
Executor的start()方法3、调用
Connector的start()方法此处的代码我就不贴出来了,可以自己去跟踪查看,我们来看看
Connector的start()方法,在其中调用了ProtocolHandler的start()方法,最终调用的是实现类org.apache.coyote.AbstractProtocol的start()方法,在该方法中又调用了org.apache.tomcat.util.net.NioEndpoint的startInternal()方法而在
NioEndpoint的startInternal()方法中最后调用了父类org.apache.coyote.AbstractProtocol的startAcceptorThreads()方法,在其中创建并开启线程来接收客户端请求
我们来看看
Acceptor中的run()方法

至此,
Tomcat启动流程就结束了