您的位置:首页 > 运维架构 > Tomcat

Tomcat源码分析之Server与Lifecycle的设计与实现

2014-03-02 19:39 507 查看
最近看Tomcat的源码的节奏还算是挺紧凑的,给人的感觉,tomcat的代码相对以前读的jetty的代码显得更有条理一些。。。当然这也是有可能是因为自己看的jetty的版本是比较老的,而看的Tomcat的代码却是比较新的Tomcat8的代码。。。。

好了闲话不多说了。。。

先来说说LifeCycle的概念。。。

这个在jetty中也有,组要是用于维护一个组件的生命周期,例如start,stop啥的。。。

另外对于有lifecycle概念的组件,一般也都还有listener的概念,当组件的状态发生改变的时候,可以有listener进行响应。。。

好啦先来看看最上层的LifeCycle接口的定义吧://生命周期的接口定义
public interface Lifecycle {

//下面定义了一些基本的状态
public static final String BEFORE_INIT_EVENT = "before_init";

/**
* The LifecycleEvent type for the "component after init" event.
*/
public static final String AFTER_INIT_EVENT = "after_init";

/**
* The LifecycleEvent type for the "component start" event.
*/
public static final String START_EVENT = "start";

/**
* The LifecycleEvent type for the "component before start" event.
*/
public static final String BEFORE_START_EVENT = "before_start";

/**
* The LifecycleEvent type for the "component after start" event.
*/
public static final String AFTER_START_EVENT = "after_start";

/**
* The LifecycleEvent type for the "component stop" event.
*/
public static final String STOP_EVENT = "stop";

/**
* The LifecycleEvent type for the "component before stop" event.
*/
public static final String BEFORE_STOP_EVENT = "before_stop";

/**
* The LifecycleEvent type for the "component after stop" event.
*/
public static final String AFTER_STOP_EVENT = "after_stop";

/**
* The LifecycleEvent type for the "component after destroy" event.
*/
public static final String AFTER_DESTROY_EVENT = "after_destroy";

/**
* The LifecycleEvent type for the "component before destroy" event.
*/
public static final String BEFORE_DESTROY_EVENT = "before_destroy";

/**
* The LifecycleEvent type for the "periodic" event.
*/
public static final String PERIODIC_EVENT = "periodic";

public static final String CONFIGURE_START_EVENT = "configure_start";

public static final String CONFIGURE_STOP_EVENT = "configure_stop";

// --------------------------------------------------------- Public Methods

/**
* Add a LifecycleEvent listener to this component.
*
* @param listener The listener to add
*/
//添加一个监听器
public void addLifecycleListener(LifecycleListener listener);

/**
* Get the life cycle listeners associated with this life cycle. If this
* component has no listeners registered, a zero-length array is returned.
*/
//返回所有的监听器
public LifecycleListener[] findLifecycleListeners();

/**
* Remove a LifecycleEvent listener from this component.
*
* @param listener The listener to remove
*/
//移除一个监听器
public void removeLifecycleListener(LifecycleListener listener);

//初始化
public void init() throws LifecycleException;

//启动
public void start() throws LifecycleException;

//停止
public void stop() throws LifecycleException;

/**
* Prepare to discard the object. The following {@link LifecycleEvent}s will
* be fired in the following order:
* <ol>
* <li>DESTROY_EVENT: On the successful completion of component
* destruction.</li>
* </ol>
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
//销毁
public void destroy() throws LifecycleException;

/**
* Obtain the current state of the source component.
*
* @return The current state of the source component.
*/
//返回当前的生命周期状态
public LifecycleState getState();

/**
* Obtain a textual representation of the current component state. Useful
* for JMX.
*/
//返回状态的名字
public String getStateName();
}

还是比较简单的吧,先是一些基本的状态和事件的定义,然后接下来是一些基本的操作,例如添加listener,移除listener,启动,停止什么的。。都还算比较的常规。。。

接下来是LifeCycle的抽象层,LifecycleBase。。。

这里就不具体的体贴出它的实现代码了,。。。LifecycleBase直接继承自LifeCycle接口,这里主要是实现了中间添加listener,移除listener的操作,这里可以可以初步理解为这里扩展成了一个listener的容器。。

另外LifecycleBase的定义中,还扩展了基本的启动,停止操作什么的。。。

例如当组件启动的时候,就需要更改当前组件的状态,并调用相应的listener。。。这里就拿初始化的方法来举例子吧: //这里扩展了init方法,这里首先设置当前组件的状态,
@Override
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
setStateInternal(LifecycleState.INITIALIZING, null, false); //设置当前的状态为INITIALIZING

try {
initInternal(); //调用该方法用于初始化,具体的实现在子类中
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.initFail",toString()), t);
}

setStateInternal(LifecycleState.INITIALIZED, null, false); //将对象设置为INITIALIZED状态
}

//具体初始化的方法啊,在子类中实现
protected abstract void initInternal() throws LifecycleException;
这里应该代码很容易能理解吧,无非就是对当前组件的装填进行验证,并修改组件的状态,当然在设置组件的状态的时候还伴随着对listener的调用。。。

最后再调用initInternal方法进行初始化,当然这个方法需要在具体的子类中进行实现。。。。

另外这里还要介绍一个比较特殊的LifeCycle的抽象层,LifecycleMBeanBase,它继承了抽象类LifecycleBase类型,其实这里看名字就能够知道这个抽象层要干些啥事情了吧。。。。来看一段代码: protected void initInternal() throws LifecycleException {

// If oname is not null then registration has already happened via
// preRegister().
if (oname == null) {
mserver = Registry.getRegistry(null, null).getMBeanServer(); //获取用到的mbserver

oname = register(this, getObjectNameKeyProperties()); //注册当前组件到mbserver
}
}

嗯,其实就是在组件的初始化的时候对当前组件在JMX上进行注册,具体Tomcat的JMX部分内容,在前面的文章中就已经说过了,这里就不详细说了。。。

也就是说,如果一个类型需要在JMX上进行注册,那么它需要继承LifeCycleMBeanBase抽象类,然后实现其中的几个抽象方法。。。

好啦,到这里位置,LifeCycle部分的内容就算差不多了。。

总的感觉,Tomcat在LifeCycle部分的设计还算是比较简单的。。。。

好啦,接下来来看看Server部分的内容吧。。。首先来看看最顶层的接口的定义:

package org.apache.catalina;

import java.io.File;

import org.apache.catalina.deploy.NamingResourcesImpl;
import org.apache.catalina.startup.Catalina;

//顶层的server接口的定义,继承了生命周期接口
public interface Server extends Lifecycle {

// ------------------------------------------------------------- Properties

/**
* Return the global naming resources.
*/
public NamingResourcesImpl getGlobalNamingResources();

/**
* Set the global naming resources.
*
* @param globalNamingResources The new global naming resources
*/
public void setGlobalNamingResources
(NamingResourcesImpl globalNamingResources);

/**
* Return the global naming resources context.
*/
public javax.naming.Context getGlobalNamingContext();

/**
* Return the port number we listen to for shutdown commands.
*/
public int getPort(); //用于监听shutdown命令的端口

/**
* Set the port number we listen to for shutdown commands.
*
* @param port The new port number
*/
public void setPort(int port); ////用于监听shutdown命令的端口

/**
* Return the address on which we listen to for shutdown commands.
*/
public String getAddress(); //用于监听shutdown命令的地址

/**
* Set the address on which we listen to for shutdown commands.
*
* @param address The new address
*/
public void setAddress(String address); //用于监听shutdown命令的地址

/**
* Return the shutdown command string we are waiting for.
*/
public String getShutdown();

/**
* Set the shutdown command we are waiting for.
*
* @param shutdown The new shutdown command
*/
public void setShutdown(String shutdown);

public ClassLoader getParentClassLoader(); //这个server对象用的classLoader,一般是catalina loader

public void setParentClassLoader(ClassLoader parent);

public Catalina getCatalina(); //获取catalina对象

public void setCatalina(Catalina catalina); //设置用的catalina对象

public File getCatalinaBase(); //一般情况下都是tomcat的根路径

public void setCatalinaBase(File catalinaBase);

public File getCatalinaHome();

public void setCatalinaHome(File catalinaHome);

public void addService(Service service); //添加service对象

public void await();

public Service findService(String name); //根据名字获取某个service

public Service[] findServices(); //获取所有的service

public void removeService(Service service); //删除一个service
}

嗯,其实最顶层的Server接口的定义也很简单,扩展了lifeCycle接口其中最重要的部分无非是对service的添加以及移除。。。

给人最大的干吼就是它是一个service的容器

好啦,接下来来看看最常用的类型StandardServer吧,这里它不光实现了Server接口,还继承了LifecycleMBeanBase类型,这里也就表示StandardServer将会被注册到JMX上面去的。。。

由于它的代码比较长,这里就不直接贴出来了。。来比较重要的属性定义吧: private Service services[] = new Service[0]; //用于保存所有的service,是一个数组啊
private final Object servicesLock = new Object();

嗯,一个service的数组。。。。嗯,容器嘛。。。

好了,这里也就稍微的来看看初始话和启动两个方法的实现吧: protected void initInternal() throws LifecycleException {

super.initInternal(); //父类的init,它里面主要是进行对象在mbserver上面注册当前对象

// Register global String cache
// Note although the cache is global, if there are multiple Servers
// present in the JVM (may happen when embedding) then the same cache
// will be registered under multiple names
onameStringCache = register(new StringCache(), "type=StringCache");

// Register the MBeanFactory
MBeanFactory factory = new MBeanFactory(); //创建MBeanFactory
factory.setContainer(this); //设置当前mbeanfactory的container
onameMBeanFactory = register(factory, "type=MBeanFactory"); //注册mbeanfactory

// Register the naming resources
globalNamingResources.init(); //初始计划名字资源

// Populate the extension validator with JARs from common and shared
// class loaders
if (getCatalina() != null) { //获取catalina对象
ClassLoader cl = getCatalina().getParentClassLoader(); //在bootstrap里面设置成了shareloader
// Walk the class loader hierarchy. Stop at the system class loader.
// This will add the shared (if present) and common class loaders
//加载classLoader里面的路径的资源,这里会向上遍历classLoader
while (cl != null && cl != ClassLoader.getSystemClassLoader()) {
if (cl instanceof URLClassLoader) {
URL[] urls = ((URLClassLoader) cl).getURLs();
for (URL url : urls) {
if (url.getProtocol().equals("file")) {
try {
File f = new File (url.toURI());
if (f.isFile() &&
f.getName().endsWith(".jar")) {
ExtensionValidator.addSystemResource(f);
}
} catch (URISyntaxException e) {
// Ignore
} catch (IOException e) {
// Ignore
}
}
}
}
cl = cl.getParent();
}
}
// Initialize our defined Services
for (int i = 0; i < services.length; i++) { //初始化service
services[i].init();
}
}
首先是初始化,这里最重要的事情其实是对当前包含的所有的service的初始化,另外还有一些其他的操作,注释应该也算是交代的比较清楚吧。。。

//父类中定义的抽象方法扩展了lifecycle的start方法,用于启动当前的对象,这里月就是启动tomcat,其实是启动server的service
@Override
protected void startInternal() throws LifecycleException {

fireLifecycleEvent(CONFIGURE_START_EVENT, null);
setState(LifecycleState.STARTING);

globalNamingResources.start();

// Start our defined Services
synchronized (servicesLock) {
for (int i = 0; i < services.length; i++) { //遍历当前的service,然后启动他们
services[i].start();
}
}
}


启动方法,这里其实最主要的也还是对Service的启动。。。

好了,到这里,Server大体的东西就这些吧,其实干货不多。。。

干活最多的地方应该在Connector部分,不过这个以后再写吧。。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: