三、Catalina的启动与停止
从图一可以看出,当Catalina收到Bootstrap的启动要求之后,会调用根组件Server的启动方法,Server再调用Service的启动方法,依次类推,这其实就是对组件这棵树的深度优先遍历。
Catalina的start方法部分代码如下:
public void start() { // 此处省略了部分代码 // Start the new server try { getServer().start(); } catch (LifecycleException e) { log.fatal(sm.getString("catalina.serverStartFail"), e); try { getServer().destroy(); } catch (LifecycleException e1) { log.debug("destroy() failed for failed Server ", e1); } return; } // 此处省略了部分代码 }
通过getServer()获取到对应的Server,然后调用其start方法。
Server对应的实现类为StandardServer,它没有重写start方法,直接在startInternal方法中写了对应的启动逻辑:
@Override protected void startInternal() throws LifecycleException { fireLifecycleEvent(CONFIGURE_START_EVENT, null); setState(LifecycleState.STARTING); globalNamingResources.start(); // Start our defined Services synchronized (servicesLock) { for (Service service : services) { service.start(); } } if (periodicEventDelay > 0) { monitorFuture = getUtilityExecutor().scheduleWithFixedDelay( () -> startPeriodicLifecycleEvent(), 0, 60, TimeUnit.SECONDS); } }
核心就是遍历所有的Service,调用每个Service的start方法。
对于其他组件也是依次类推,可以看出,上级组件对下级组件的调用是直接调用其start方法,因为这些组件都实现了生命周期接口,这就是组合模式的优点之一。可以把所有组件一视同仁的调用,而不用管其中的实现细节。这也方便了对组件的增减,使系统设计更加弹性、易于扩展。
对于组件的停止逻辑也类似,就不逐一介绍了,有兴趣的可以看一下对应的源码。
总结
到本篇为止,我们整体的了解了Tomcat的组件结构及初始化、启动的流程。
而这些都是以概览的方式进行的,并没有对具体组件的功能进行学习。在接下来的章节会对这些组件进行详细介绍。
如果想看这些组件的具体代码实现,可以看一下这些接口对应的实现类,位置图下图的core文件夹:
图三
这个文件夹下存放了一些以Standard开头的实现类,例如StandardServer、StandardService等。
图四
可见内容还是很多的,有兴趣的可以提前看一下。