先来看看Tomcat的架构吧:
本文将介绍Tomcat启动时涉及到的组件和初始化,启动过程。
1:Tomcat启动从org.apache.catalina.startup的main()函数开始。
public static void main(String args[]) {
if (daemon == null) {
daemon = new Bootstrap();
try {
daemon.init();
} catch (Throwable t) {
t.printStackTrace();
return;
}
}
.....此处省略部分代码...
daemon.load(args);
daemon.start();
.....此处省略部分代码...
}
此处看到启动过程涉及到3个函数:init(),load(),start()。先来分析一下init()吧。
public void init()
throws Exception
{
.....此处省略部分代码.......
initClassLoaders();
.....此处省略部分代码.......
//下面通过反射机制调用Catalina的setParentClassLoader方法
Class startupClass =
catalinaLoader.loadClass
("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.newInstance();
// Set the shared extensions class loader
if (log.isDebugEnabled())
log.debug("Setting startup class properties");
String methodName = "setParentClassLoader";
Class paramTypes[] = new Class[1];
paramTypes[0] = Class.forName("java.lang.ClassLoader");
Object paramValues[] = new Object[1];
paramValues[0] = sharedLoader;
Method method =
startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues);
catalinaDaemon = startupInstance;
}
private void initClassLoaders() {
try {
commonLoader = createClassLoader("common", null);
if( commonLoader == null ) {
// no config file, default to this loader - we might be in a 'single' env.
commonLoader=this.getClass().getClassLoader();
}
catalinaLoader = createClassLoader("server", commonLoader);
sharedLoader = createClassLoader("shared", commonLoader);
} catch (Throwable t) {
log.error("Class loader creation threw exception", t);
System.exit(1);
}
}
initClassLoaders() 初始化了三个类加载器。接下来catalina就可以用这三种类型的classLoader来负责装配容器了。
接下来是load()方法。它其实会通过反射机制去执行catalina的load()方法。
public void load() {
//……
//初始化Digester组件,定义了解析规则
Digester digester = createStartDigester();
//……中间略去代码若干,主要作用为将server.xml文件转换为输入流
try {
inputSource.setByteStream(inputStream);
digester.push(this);
//通过Digester解析这个文件,在此过程中会初始化各个组件实例及其依赖关系
digester.parse(inputSource);
inputStream.close();
} catch (Exception e) {
}
// 调用Server的initialize方法,初始化各个组件
if (getServer() instanceof Lifecycle) {
try {
getServer().initialize();
} catch (LifecycleException e) {
if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
throw new java.lang.Error(e);
else
log.error("Catalina.start", e);
}
}
}
可以看出load的两个任务:使用Digester组件按照给定的规则解析server.xml、调用Server的initialize方法。这里的Server是从StandardService中的getServer()得来的。让我们进入Server的init()中吧。init()------>initialize()。public void initialize()
throws LifecycleException
{
......此处省略部分代码......
lifecycle.fireLifecycleEvent(INIT_EVENT, null);
initialized = true;
......此处省略部分代码......
// Initialize our defined Services
for (int i = 0; i < services.length; i++) {
services[i].initialize();
}
}
如果你还有兴趣追溯下去的话,你会发现services的initialize()中还会进行connector的初始化等。这样就能完成各级组件的初始化。
接下来是start()函数了。
public void start()
throws Exception {
if( catalinaDaemon==null ) init();
Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);
method.invoke(catalinaDaemon, (Object [])null);
}
可以看出还是通过反射机制调用catalina的start()方法。public void start() {
......此处省略部分代码......
// Start the new server
if (getServer() instanceof Lifecycle) {
try {
((Lifecycle) getServer()).start();
} catch (LifecycleException e) {
log.error("Catalina.start: ", e);
}
}
......此处省略部分代码......
try {
// Register shutdown hook
if (useShutdownHook) {
if (shutdownHook == null) {
shutdownHook = new CatalinaShutdownHook();
}
Runtime.getRuntime().addShutdownHook(shutdownHook);
......此处省略部分代码......
}
当你看到了if (getServer() instanceof Lifecycle) {
try {
((Lifecycle) getServer()).start();
} catch (LifecycleException e) {
log.error("Catalina.start: ", e);
}
}
这段代码时,你很容易联想到我们之前的load方法,当时是采用级联方式的进行load的。同样这里也是那样。不断的通过级联进行start。那么service,Engine,Host,Connector等组件容器都会启动。shutdownHook 是我们注册的一个Hook。tomcat中提供了hook,可以在关闭过程中运行一些代码,执行清理的工作。shutdown
hook是一个java.lang.Thread子类的实例,shutdown hook会由jvm启动,不用你自己启动。
protected class CatalinaShutdownHook extends Thread {
public void run() {
......此处省略部分代码......
}
}
这样就完成了整个Tomcat的启动了。当客户端有请求进来了,就可以通过connector等组件的配合完成整个的请求处理。
作者:keep_moving_cqu 发表于2013-11-25 0:31:48 原文链接
阅读:93 评论:0 查看评论