跟踪Tomcat源码,为VERSION 10.1.26例,具体环境搭建见上一节见Tomcat10.1.26源码导入IDEA2024.1.4问题
,启动脚本startup.bat,启动的时候要找main方法。
初始化
初始化及启动时序图如下,主要对Tomcat配置文件进行加载,监听对应端口号,准备接收客户端请求:
找到mian方法
- startup.bat中执行catalina.bat
- catalina.bat中定义MAINCLASS指定了Bootstrap
初始化
主要加载类加载器,初始化Vatalina等容器
- Bootstrap的main方法中调用init初始化
-
init方法中,通过反射创建Catalina及初始化类加载器。
-
把初始化后的bootstrap赋值给daemon
- 如果执行的start命令调用load方法
- 调用Catalina的load方法,并传递参数
- Catalina的load方法中进行了一些初始化工作,构造Digester对象用来解析XML。
-
Catalina容器中创建了Server,初始化Server。
Server接口实现了Lifecycle,Lifecycle的实现类LifecycleBase。LifecycleBase中init方法,init方法中调用initInternal。在Server的实现类StandardServer中找到initInternal。整个流程用到了模板设计模式。
-
Server调用多个Service的init方法
- 和上面找到Server初始化方法步骤一致,找到Service实现类StandService调用initInternal方法,首先Service初始化Engine。
- 之后,Service初始化Executor
- Service 初始化Listener,初始化Connector init
- 和上面相同步骤,找到Connector实现类的initInternal方法,首先创建CoyoteAdapter
- 之后,调用protocolHandler的初始化方法
-
如果是HTTP请求这里使用AbstractHttp11Protocol#init
-
调用AbstractHttp11Protocol父类初始化方法
- ProtocolHandler中又调用了自身组件Endpoint的初始化方法
-
Endpoint初始化方法中调用bind。(Endpoint的作用是监听端口号,接收socket请求。)
-
bind方法也是模板方法设计模式。Endpoint两个实现类Nio2Endpoint、NioEndpoint。
- NioEndpoint#bind方法中,绑定了端口号和信息。
start启动
启动组件
- BootStrap start,调用Catalina start
- Catalina调用Server start
- 同样通过Lifecycle、LifecycleBase跟踪到start方法中的startInternal方法。追踪到StandardServer方法中的startInternal方法。该方法中遍历调用Service方法。
- Service调用Engine start、Listener start、Connector start。和init步骤类似。
- Connector startInternal方法中调用了protocolHandler#start
- ProtocolHandler的实现类AbstractProtocol中调用了endpoint#start
- Endpoint#startInternal开启接收请求线程
- 初始化了一些Acceptor,接收客户端请求对象,开启线程
- 找到Acceptor run方法。关注Endpoint#serverSocketAcceptor
- Endpoint#serverSocketAcceptor,监听客户端发起的accept请求。
综上,Tomcat统一按照生命周期管理接口LifeCycle定义启动,调用init逐步初始化组件,调用start进行启动。每一级组件完成自身处理,以及子组件响应生命周期。