Server组件
Server组件具体实现类StandardServer。
Server继承了LifecycleBase,它的生命周期被统一管理
它的子组件是Service,因此它还需要管理Service的生命周期,即在启动时调用Service组件的启动方法,在停止时调用它们的停止方法。Server在内部维护了若干Service组件,它是以数组来保存的,那Server是如何添加一个Service到数组中的呢?
@Override public void addService(Service service) { service.setServer(this); synchronized (servicesLock) { // 长度+1的数组并没有一开始就分配一个很长的数组 // 而是在添加的过程中动态地扩展数组长度,当添加一个新的Service实例时 // 会创建一个新数组并把原来数组内容复制到新数组,节省内存 Service results[] = new Service[services.length + 1]; // 复制老数据 System.arraycopy(services, 0, results, 0, services.length); results[services.length] = service; services = results; // 启动Service组件 if (getState().isAvailable()) { try { service.start(); } catch (LifecycleException e) { // Ignore } } // 触发监听事件 support.firePropertyChange("service", null, service); } }
Server组件还需要启动一个Socket来监听停止端口,所以才能通过shutdown命令关闭Tomcat。
上面Catalina的启动方法最后一行代码就是调用Server#await。
在await方法里会创建一个Socket监听8005端口,并在一个死循环里接收Socket上的连接请求,如果有新的连接到来就建立连接,然后从Socket中读取数据;如果读到的数据是停止命令“SHUTDOWN”,就退出循环,进入stop流程。
Service组件
Service组件的具体实现类StandardService
public class StandardService extends LifecycleBase implements Service { //名字 private String name = null; //Server实例 private Server server = null; //连接器数组 protected Connector connectors[] = new Connector[0]; private final Object connectorsLock = new Object(); //对应的Engine容器 private Engine engine = null; //映射器及其监听器 protected final Mapper mapper = new Mapper(); protected final MapperListener mapperListener = new MapperListener(this);
StandardService继承了LifecycleBase抽象类,此外StandardService中还有一些我们熟悉的组件,比如Server、Connector、Engine和Mapper。
Tomcat支持热部署,当Web应用的部署发生变化,Mapper中的映射信息也要跟着变化,MapperListener就是监听器,监听容器的变化,并把信息更新到Mapper。
Service启动方法
protected void startInternal() throws LifecycleException { // 1. 触发启动监听器 setState(LifecycleState.STARTING); // 2. 先启动Engine,Engine会启动它子容器 if (engine != null) { synchronized (engine) { engine.start(); } } // 3. 再启动Mapper监听器 mapperListener.start(); // 4.最后启动连接器,连接器会启动它子组件,比如Endpoint synchronized (connectorsLock) { for (Connector connector: connectors) { if (connector.getState() != LifecycleState.FAILED) { connector.start(); } } } }
Service先后启动Engine、Mapper监听器、连接器。
内层组件启动好了才能对外提供服务,才能启动外层的连接器组件。而Mapper也依赖容器组件,容器组件启动好了才能监听它们的变化,因此Mapper和MapperListener在容器组件之后启动。