上一篇中大概介绍了tomcat的几大组件的大概作用和各自所处的位置,这里再来看下tomcat在初始化的过程中主要干了什么事情
Bootstrap
Bootstrap是tomcat的入口类,所以我们先来看这个类。
- 在看main方法之前我们先看Bootstrap的最上面,这里有一个静态代码块,从这段代码块中我们可以看出它就是对一些环境变量进行了设置,然后设置catalinaHomeFile(安装目录)和catalinaBaseFile(工作目录)。
- 我们再看main方法,main方法大致上做了3件事情,init(初始化)load(加载资源文件,初始化组件),start(启动组件 下一章描述)
2.1 init 里面主要干了一件事情 ,就是初始化了3个类加载器,对于tomcat而言它打破了JVM的双亲委派机制,它构建了自己的commonLoader、catalinaLoader、sharedLoader。
2.2 在看load方法之前我们需要先来看下面2张类图
对于tomcat中的组件而言,他们有一个共同的父类接口Lifecycle,这个接口内给组件定义了完整的生命周期。
我们在来接着看Bootstrap中的load方法,在上面的Bootstrap的init之后我们可以看到 daemon = bootstrap;这一句也就是说下面这个load实际上调用的就是Bootstrap的load方法,我们再跟进去看一下到底干了什么。
然后我们跟进去发下它其实是通过反射调用catalina的load方法
这里实际调用的是StandardServer的initInternal,在看initInternal方法之前我们先来了解一下LifecycleBase这个类。
LifecycleBase这个类使用到了模板方法模式,它定义了一个动作需要经历哪几个历程需要干些什么事情,比如init方法,在初始化前后都需要发出通知,告诉监听器当前处于什么生命历程(这里使用到了事件驱动编程有兴趣的可以了解一下)。start,destory等方法同理。
再回到我们的server初始化过程,对于tomcat而言每个容器它都提供了一个标准实现,StandardServer就是server的标准实现。
关键在于这个地方,我们很清楚的看到这里实现了service的初始化,我们接着往下看,到StandardService#initInternal()这个方法里面去看下到底干了什么。
首先我们来看上半段,这里我们可以看出调用了engine的init方法实现了对engine的初始化,那按照这个套路我们往下推断,是不是engine中初始化了host,然后host中初始化了context,这样一级级的初始化?当我们跟到StandardEngine#initInternal()会发现其实并不是这样。
在这个方法内没有再接着对host进行初始化(当我们继续跟下去后会发现其实host之后的初始化发生在start阶段)。
我们再回到StandardService#initInternal()这个方法,刚才我们分析了engine的初始化,下面对线程池,连接器进行了初始化。
再进入到连接器的初始化方法Connector#initInternal()内
我们从这段里面可以看到上一章提到的connector中2个重要的组件,CoyoteAdapter和ProtocolHandler,然后再protocolHandler的父类AbstractProtocol中实现了对EndPoint的初始化