Tomcat 的整体结构图: java
Connector | Container |
---|---|
负责和外界取得联系,即创建链接(一个Connetor组件只能处理一种请求协议,例如一个Connector组件不能既处理http方式的请求又能处理https请求,所以须要多个Connector组件。) | 负责处理Connector接受的请求,主要是处理内部事务(Container包含了Engine,Host,Context,Wrapper四个组件,负责处理请求相关的逻辑) |
Service 只是在 Connector 和 Container 外面多包一层,把它们组装在一块儿,对外提供服务,一个 Service 能够设置多个 Connector,可是只能有一个 Container 容器。 Server控制Tomcat的整个生命周期。数组
Service接口 | Lifecycle接口 |
---|---|
关联Connector和Container,同时初始化它下面的其余组件 | 控制全部组件的生命周期 |
StandardService实现了Service接口和Lifecycle接口,这样它就能够控制它下面组件的生命周期了;除了对Service和Lifecycle接口方法的实现它还有几个方法是用于事件监听方法的实现。app
图 Service 接口 性能
源码剖析:
下面看一下 StandardService 中主要的几个方法实现的代码,下面是 setContainer 和 addConnector 方法的源码:
清单 1. StandardService. SetContainerthis
public void setContainer(Container container) {
Container oldContainer = this.container;
if ((oldContainer != null) && (oldContainer instanceof Engine))
((Engine) oldContainer).setService(null);
this.container = container;
if ((this.container != null) && (this.container instanceof Engine))
((Engine) this.container).setService(this);
if (started && (this.container != null) && (this.container instanceof Lifecycle)) {
try {
((Lifecycle) this.container).start();
} catch (LifecycleException e) {
;
}
}
synchronized (connectors) {
for (int i = 0; i < connectors.length; i++)
connectors[i].setContainer(this.container);
}
if (started && (oldContainer != null) && (oldContainer instanceof Lifecycle)) {
try {
((Lifecycle) oldContainer).stop();
} catch (LifecycleException e) {
;
}
}
support.firePropertyChange("container", oldContainer, this.container);
}
复制代码
这段代码很简单,其实就是先判断当前的这个 Service 有没有已经关联了 Container,若是已经关联了,那么去掉这个关联关系—— oldContainer.setService(null)。若是这个 oldContainer 已经被启动了,结束它的生命周期。而后再替换新的关联、再初始化并开始这个新的 Container 的生命周期。最后将这个过程通知感兴趣的事件监听程序。
清单 2. StandardService. addConnectorspa
public void addConnector(Connector connector) {
synchronized (connectors) {
connector.setContainer(this.container);
connector.setService(this);
Connector results[] = new Connector[connectors.length + 1];
System.arraycopy(connectors, 0, results, 0, connectors.length);
results[connectors.length] = connector;
connectors = results;
if (initialized) {
try {
connector.initialize();
} catch (LifecycleException e) {
e.printStackTrace(System.err);
}
}
if (started && (connector instanceof Lifecycle)) {
try {
((Lifecycle) connector).start();
} catch (LifecycleException e) {
;
}
}
support.firePropertyChange("connector", null, connector);
}
}
复制代码
上面是 addConnector 方法,这个方法也很简单,首先是设置关联关系,而后是初始化工做,开始新的生命周期。code
注意: Connector 用的是数组而不是 List 集合,这个从性能角度考虑能够理解,有趣的是这里用了数组可是并无向咱们日常那样,一开始就分配一个固定大小的数组,它这里的实现机制是:从新建立一个当前大小的数组对象,而后将原来的数组对象 copy 到新的数组中,这种方式实现了相似的动态数组的功能,这种实现方式,值得咱们之后拿来借鉴。cdn
Server 的任务:就是要可以提供一个接口让其它程序可以访问到这个 Service 集合、同时要维护它所包含的全部 Service 的生命周期,包括如何初始化、如何结束服务、如何找到别人要访问的 Service。对象
Server 类结构图 blog
它的标准实现类 StandardServer 实现了上面这些方法,同时也实现了 Lifecycle、MbeanRegistration 两个接口的全部方法,下面主要看一下 StandardServer 重要的一个方法 addService 的实现:
public void addService(Service service) {
service.setServer(this);
synchronized (services) {
Service results[] = new Service[services.length + 1];
System.arraycopy(services, 0, results, 0, services.length);
results[services.length] = service;
services = results;
if (initialized) {
try {
service.initialize();
} catch (LifecycleException e) {
e.printStackTrace(System.err);
}
}
if (started && (service instanceof Lifecycle)) {
try {
((Lifecycle) service).start();
} catch (LifecycleException e) {
;
}
}
support.firePropertyChange("service", null, service);
}
}
复制代码
从上面第一句就知道了 Service 和 Server 是相互关联的,Server 也是和 Service 管理 Connector 同样管理它,也是将 Service 放在一个数组中,后面部分的代码也是管理这个新加进来的 Service 的生命周期。Tomcat6 中也是没有什么变化的。