Main函数启动

源码org.apache.catalina.startup.Bootstrap这个是启动类,main函数就在这个类中.

第一件事,就是调用Bootstrap.init()方法,我们来看看这个方法做了什么处理.

  1. 首先初始化它的静态块代码,设置catalina.home, catalina.base等相应的环境变量.

  2. 调用 initClassLoaders()

  3. Tomcat当前主线程的ContextClassLoader设置为catalinaLoader

  4. SecurityClassLoader设置为catalinaLoader

  5. 通过catalinaLoader.loadClass来加载org.apache.catalina.startup.Catalina类并实例化一个该对象为startupInstance

  6. 然后,通过反射来设置startupInstance对象的setParentClassLoader方法来设置它的parent classloader为sharedLoader.

  7. 最后,将catalinaDaemon的值,设置为startupInstance.

Tomcat的properties管理类 CatalinaProperties

在进入classloader初始化之前,我们来看看Tomcat加载properties的管理类,就是org.apache.catalina.startup.CatalinaProperties类.

Tomcat加载不同的classLoader,是通过String value = CatalinaProperties.getProperty(name + ".loader");这个配置来加载类的.

CatalinaProperties类,通过源码可知,它是加载tomcat目录下的conf/catalina.properties文件的.

initClassLoaders() 方法

    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) {
            handleThrowable(t);
            log.error("Class loader creation threw exception", t);
            System.exit(1);
        }
    }

可以看到该方法初始化了三个classloder,分别是commonLoader, catalinaLoader, sharedLoader.而且commonLoadercatalinaLoadersharedLoader的父classloader.

commonLoader

所以,我们看看这个配置文件中common.loader的value可知是如下:

common.loader="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"

在这里,可以看到,Tomcat是单目录,多实例结构的。catalina.base是实例的目录位置,catalina.home是tomcat安装目录的位置.但一般情况下,我们的catalina.basecatalina.home是相同的.

所以,可以知道commonLoader负载加载上面指定的"${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"这些类的.

根据这样子的情况,我们可以知道,如果想让一个依赖包,让所有的应用都加载的话,可以将这些依赖包,放到以上指定的目录中即可.(不过,一般情况下也不建议这样子做,一个Tomcat中多个应用要加载不同版本的jar包,这样子就会出问题了)

catalinaLoader

可以看到,该loader的父loader是commonLoader.所以通过catalinaLoader加载的类,都会让commonLoader先尝试加载。

该loader加载的是server.loader=这个配置指定的路径的.可以看到,默认情况下它是空的。

sharedLoader

可以看到,该loader的父loader是commonLoader.所以通过sharedLoader加载的类,都会让commonLoader先尝试加载。

该loader加载的是shared.loader=这个配置指定的路径的.可以看到,默认情况下它是空的