转载

tomcat源码系列二(初始化启动)

Tomcat 的结构很复杂,但是 Tomcat 也非常的模块化,找到了 Tomcat 最核心的模块,您就抓住了 Tomcat 的“七寸”。下面是 Tomcat 的总体结构图:

tomcat源码系列二(初始化启动)

从上图中可以看出 Tomcat 的心脏是两个组件:Connector 和 Container,关于这两个组件将在后面详细介绍。Connector 组件是可以被替换,这样可以提供给服务器设计者更多的选择,因为这个组件是如此重要,不仅跟服务器的设计的本身,而且和不同的应用场景也十分相关,所以一个 Container 可以选择对应多个 Connector。多个 Connector 和一个 Container 就形成了一个 Service,Service 的概念大家都很熟悉了,有了 Service 就可以对外提供服务了,但是 Service 还要一个生存的环境,必须要有人能够给她生命、掌握其生死大权,那就非 Server 莫属了。所以整个 Tomcat 的生命周期由 Server 控制。

通过关键类来看Tomcat结构

tomcat源码系列二(初始化启动)

Tomcat启动

当通过 ./startup.sh 脚本或直接通过 java 命令来启动 Bootstrap 时,Tomcat 的启动过程就正式开始了,启动的入口点就是 Bootstrap 类的 main 方法。

启动的过程分为三步,分别为:

1. Bootstrap初始化
	Bootstrap bootstrap = new Bootstrap();
	bootstrap.init();
	daemon = bootstrap;
2. load和start
	daemon.load(args);
	daemon.start();

bootstrap.init()

先贴出源码,在源码中标注了顺序,下面详解

/**
 * Initialize daemon.
 */
public void init()
    throws Exception
{

    //1. Set Catalina path
    setCatalinaHome();
    setCatalinaBase();

	//2. 初始化classLoader
    initClassLoaders();

    Thread.currentThread().setContextClassLoader(catalinaLoader);

    SecurityClassLoad.securityClassLoad(catalinaLoader);

    // Load our startup class and call its process() method
    if (log.isDebugEnabled())
        log.debug("Loading startup class");
    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);
    //3. 设置parentClassLoader
    method.invoke(startupInstance, paramValues);

	// 4. 将catalinaDaemon赋值为Catalia实例
    catalinaDaemon = startupInstance;

}
  1. Set Catalina path (设置catalina的路径信息)
  2. initClassLoaders(初始化三个ClassLoader)
  3. 设置Catalina的parentClassLoader
  4. 将catalinaDaemon赋值为Catalia实例

daemon.load(args)

贴出源码:

/**
 * Load daemon.
 */
private void load(String[] arguments)
    throws Exception {

    // Call the load() method
    String methodName = "load";
    Object param[];
    Class<?> paramTypes[];
    if (arguments==null || arguments.length==0) {
        paramTypes = null;
        param = null;
    } else {
        paramTypes = new Class[1];
        paramTypes[0] = arguments.getClass();
        param = new Object[1];
        param[0] = arguments;
    }
    Method method =
        catalinaDaemon.getClass().getMethod(methodName, paramTypes);
    if (log.isDebugEnabled())
        log.debug("Calling startup class " + method);
    method.invoke(catalinaDaemon, param);

}

可以看出这个做的主要事情是调用catalinaDaemon.load()

在第一步init的时候 知道catalinaDaemon为Catalina的实例,所以看下catalina.load(),其中的关键性代码如下:

//1. Create and execute our Digester
Digester digester = createStartDigester();
InputSource inputSource = null;
InputStream inputStream = null;
File file = null;
// 2.读取配置文件conf/server.xml
file = configFile();
inputStream = new FileInputStream(file);
inputSource = new InputSource(file.toURI().toURL().toString());
inputSource.setByteStream(inputStream);
digester.push(this);
// 3.解析配置文件
digester.parse(inputSource);
getServer().setCatalina(this);
// Stream redirection
initStreams();
// 4.初始化server主要初始化声明周期
getServer().init();
原文  https://seemoonup.github.io/2018/11/13/tech/tomcat/tomcat源码系列二(初始化启动)/
正文到此结束
Loading...