Tomcat启动部分源代码分析(三) -- 载入

二. 载入

2. Bootstrap的#Bootstrap#load(String[] arguments)方法。

方法的源代码如下述所示:

Java代码 Tomcat启动部分源代码分析(三) -- 载入 - guoyang1982 - 游龙

  1. private void load(String[] arguments) throws Exception {   
  2.     // 要调用的方法名   
  3.     String methodName = "load";   
  4.     // 参数名   
  5.     Object param[];   
  6.     // 参数值   
  7.     Class paramTypes[];   
  8.     if (arguments == null || arguments.length == 0) {   
  9.         paramTypes = null;   
  10.         param = null;   
  11.     } else {   
  12.         paramTypes = new Class[1];   
  13.         paramTypes[0] = arguments.getClass();   
  14.         param = new Object[1];   
  15.         param[0] = arguments;   
  16.     }   
  17.     Method method = catalinaDaemon.getClass().getMethod(methodName, paramTypes);   
  18.     if (log.isDebugEnabled())   
  19.         log.debug("Calling startup class " + method);   
  20.        
  21.     // 这里会使程序产生两个分支,调用Catalina#load()和Catalina#load(String args[])两个方法。   
  22.     method.invoke(catalinaDaemon, param);   
  23.   
  24. }  

private void load(String[] arguments) throws Exception { // 要调用的方法名 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); // 这里会使程序产生两个分支,调用Catalina#load()和Catalina#load(String args[])两个方法。 method.invoke(catalinaDaemon, param); }

这时就该轮到查看Catalina的两个load()方法了。先看看带参数的版本:

Java代码 Tomcat启动部分源代码分析(三) -- 载入 - guoyang1982 - 游龙

  1. public void load(String args[]) {   
  2.   
  3.     try {   
  4.         if (arguments(args))   
  5.             load();   
  6.     } catch (Exception e) {   
  7.         e.printStackTrace(System.out);   
  8.     }   
  9. }  

public void load(String args[]) { try { if (arguments(args)) load(); } catch (Exception e) { e.printStackTrace(System.out); } }

代码很短,在内部还调用了无参数的load()版本。在这之前,先来看一下arguments()方法:

Java代码 Tomcat启动部分源代码分析(三) -- 载入 - guoyang1982 - 游龙

  1. protected boolean arguments(String args[]) {   
  2.   
  3.     boolean isConfig = false;   
  4.   
  5.     if (args.length < 1) {   
  6.         usage();   
  7.         return (false);   
  8.     }   
  9.   
  10.     for (int i = 0; i < args.length; i++) {   
  11.         if (isConfig) {   
  12.             // server.xml的路径   
  13.             configFile = args[i];   
  14.             isConfig = false;   
  15.         } else if (args[i].equals("-config")) {   
  16.             // 下一个参数是server.xml的路径   
  17.             isConfig = true;   
  18.         } else if (args[i].equals("-nonaming")) {   
  19.             // 取消naming支持   
  20.             setUseNaming(false);   
  21.         } else if (args[i].equals("-help")) {   
  22.             // 帮助   
  23.             usage();   
  24.             return (false);   
  25.         } else if (args[i].equals("start")) {   
  26.             // 开启   
  27.             starting = true;   
  28.             stopping = false;   
  29.         } else if (args[i].equals("stop")) {   
  30.             // 关闭   
  31.             starting = false;   
  32.             stopping = true;   
  33.         } else {   
  34.             usage();   
  35.             return (false);   
  36.         }   
  37.     }   
  38.   
  39.     return (true);   
  40.   
  41. }  

protected boolean arguments(String args[]) { boolean isConfig = false; if (args.length < 1) { usage(); return (false); } for (int i = 0; i < args.length; i++) { if (isConfig) { // server.xml的路径 configFile = args[i]; isConfig = false; } else if (args[i].equals("-config")) { // 下一个参数是server.xml的路径 isConfig = true; } else if (args[i].equals("-nonaming")) { // 取消naming支持 setUseNaming(false); } else if (args[i].equals("-help")) { // 帮助 usage(); return (false); } else if (args[i].equals("start")) { // 开启 starting = true; stopping = false; } else if (args[i].equals("stop")) { // 关闭 starting = false; stopping = true; } else { usage(); return (false); } } return (true); }

主要对可以使用的一些参数进行了一些判断,如果参数有误就返回false。

如果arguments()返回true,两个分支就合二为一了,都进入了无参数的load()。

下面来重点看下这个方法:

Java代码 Tomcat启动部分源代码分析(三) -- 载入 - guoyang1982 - 游龙

  1. public void load() {   
  2.   
  3.     long t1 = System.nanoTime();   
  4.   
  5.     // 初始化Catalina环境路径,CatalinaHome和CatalinaBase   
  6.     initDirs();   
  7.   
  8.     // 初始化naming   
  9.     initNaming();   
  10.   
  11.     // 创建一个Digester对象,主要用于xml文件的读取,本实例中的Digester用于server.xml的读取。   
  12.     // 在createStartDigester()中队server.xml中的xml样式与具体的类进行了绑定。   
  13.     Digester digester = createStartDigester();   
  14.   
  15.     InputSource inputSource = null;   
  16.     InputStream inputStream = null;   
  17.     File file = null;   
  18.     try {   
  19.         // server.xml文件   
  20.         file = configFile();   
  21.         inputStream = new FileInputStream(file);   
  22.         inputSource = new InputSource("file://" + file.getAbsolutePath());   
  23.     } catch (Exception e) {   
  24.         ;   
  25.     }   
  26.     if (inputStream == null) {   
  27.         try {   
  28.             // 在jar包中寻找server.xml   
  29.             inputStream = getClass().getClassLoader().getResourceAsStream(getConfigFile());   
  30.             inputSource = new InputSource(getClass().getClassLoader().getResource(   
  31.                     getConfigFile()).toString());   
  32.         } catch (Exception e) {   
  33.             ;   
  34.         }   
  35.     }   
  36.   
  37.     if (inputStream == null) {   
  38.         try {   
  39.             // 在jar包中寻找config-embed.xml   
  40.             inputStream = getClass().getClassLoader().getResourceAsStream("server-embed.xml");   
  41.             inputSource = new InputSource(getClass().getClassLoader().getResource(   
  42.                     "server-embed.xml").toString());   
  43.         } catch (Exception e) {   
  44.             ;   
  45.         }   
  46.     }   
  47.   
  48.     if ((inputStream == null) && (file != null)) {   
  49.         // 实在找不到了,直接返回   
  50.         log.warn("Can't load server.xml from " + file.getAbsolutePath());   
  51.         return;   
  52.     }   
  53.   
  54.     try {   
  55.         inputSource.setByteStream(inputStream);   
  56.         digester.push(this);   
  57.         digester.parse(inputSource);   
  58.         inputStream.close();   
  59.     } catch (Exception e) {   
  60.         log.warn("Catalina.start using " + getConfigFile() + ": ", e);   
  61.         return;   
  62.     }   
  63.   
  64.     // 重定向输出流和错误流   
  65.     initStreams();   
  66.   
  67.     if (server instanceof Lifecycle) {   
  68.         try {   
  69.             // Server初始化   
  70.             server.initialize();   
  71.         } catch (LifecycleException e) {   
  72.             log.error("Catalina.start", e);   
  73.         }   
  74.     }   
  75.   
  76.     long t2 = System.nanoTime();   
  77.     if (log.isInfoEnabled())   
  78.         log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");   
  79.   
  80. }  

public void load() { long t1 = System.nanoTime(); // 初始化Catalina环境路径,CatalinaHome和CatalinaBase initDirs(); // 初始化naming initNaming(); // 创建一个Digester对象,主要用于xml文件的读取,本实例中的Digester用于server.xml的读取。 // 在createStartDigester()中队server.xml中的xml样式与具体的类进行了绑定。 Digester digester = createStartDigester(); InputSource inputSource = null; InputStream inputStream = null; File file = null; try { // server.xml文件 file = configFile(); inputStream = new FileInputStream(file); inputSource = new InputSource("file://" + file.getAbsolutePath()); } catch (Exception e) { ; } if (inputStream == null) { try { // 在jar包中寻找server.xml inputStream = getClass().getClassLoader().getResourceAsStream(getConfigFile()); inputSource = new InputSource(getClass().getClassLoader().getResource( getConfigFile()).toString()); } catch (Exception e) { ; } } if (inputStream == null) { try { // 在jar包中寻找config-embed.xml inputStream = getClass().getClassLoader().getResourceAsStream("server-embed.xml"); inputSource = new InputSource(getClass().getClassLoader().getResource( "server-embed.xml").toString()); } catch (Exception e) { ; } } if ((inputStream == null) && (file != null)) { // 实在找不到了,直接返回 log.warn("Can't load server.xml from " + file.getAbsolutePath()); return; } try { inputSource.setByteStream(inputStream); digester.push(this); digester.parse(inputSource); inputStream.close(); } catch (Exception e) { log.warn("Catalina.start using " + getConfigFile() + ": ", e); return; } // 重定向输出流和错误流 initStreams(); if (server instanceof Lifecycle) { try { // Server初始化 server.initialize(); } catch (LifecycleException e) { log.error("Catalina.start", e); } } long t2 = System.nanoTime(); if (log.isInfoEnabled()) log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms"); }

initDirs()和initNaming()主要是值的设定,就不细说了。

createStartDigester()方法主要是实例化一个Digester对象,并提供了xml中的模式与java类对象的绑定。对Digester并没有什么研究,只是通过JavaDoc大致了解了下程序的运作过程。

Java代码 Tomcat启动部分源代码分析(三) -- 载入 - guoyang1982 - 游龙

  1. protected Digester createStartDigester() {   
  2.     long t1 = System.currentTimeMillis();   
  3.     // 初始化digester   
  4.     Digester digester = new Digester();   
  5.     digester.setValidating(false);   
  6.     digester.setRulesValidation(true);   
  7.     HashMap<Class, List<String>> fakeAttributes = new HashMap<Class, List<String>>();   
  8.     ArrayList<String> attrs = new ArrayList<String>();   
  9.     attrs.add("className");   
  10.     fakeAttributes.put(Object.class, attrs);   
  11.     digester.setFakeAttributes(fakeAttributes);   
  12.     digester.setClassLoader(StandardServer.class.getClassLoader());   
  13.   
  14.     // 三个参数分别为:1. xml标签的名字;2. 默认的Java类名;3.如果标签中有这个属性,那么它就覆盖掉默认的Java类名   
  15.     // 具体到下边的这条语句,就是处理"Server"标签,并实例化一个StandardServer类的实例   
  16.     // 如果Server标签有一个叫className的属性,就会覆盖掉默认的Java类型。   
  17.     digester.addObjectCreate("Server", "org.apache.catalina.core.StandardServer", "className");   
  18.        
  19.     // 设定一个SetPropertiesRule,这个规则是用于堆栈顶端元素的属性设置   
  20.     digester.addSetProperties("Server");   
  21.   
  22.     // 三个参数分别为:1.xml标签名;2.要设定的"父对象"(与继承无关)的方法名;3.方法参数的Java类型   
  23.     digester.addSetNext("Server", "setServer", "org.apache.catalina.Server");   
  24.   
  25.     digester.addObjectCreate("Server/GlobalNamingResources", "org.apache.catalina.deploy.NamingResources");   
  26.     digester.addSetProperties("Server/GlobalNamingResources");   
  27.     digester.addSetNext("Server/GlobalNamingResources", "setGlobalNamingResources",   
  28.             "org.apache.catalina.deploy.NamingResources");   
  29.   
  30.     digester.addObjectCreate("Server/Listener", null, "className");   
  31.     digester.addSetProperties("Server/Listener");   
  32.     digester.addSetNext("Server/Listener", "addLifecycleListener",   
  33.             "org.apache.catalina.LifecycleListener");   
  34.   
  35.     digester.addObjectCreate("Server/Service", "org.apache.catalina.core.StandardService", "className");   
  36.     digester.addSetProperties("Server/Service");   
  37.     digester.addSetNext("Server/Service", "addService", "org.apache.catalina.Service");   
  38.   
  39.     digester.addObjectCreate("Server/Service/Listener", null, "className");   
  40.     digester.addSetProperties("Server/Service/Listener");   
  41.     digester.addSetNext("Server/Service/Listener", "addLifecycleListener",   
  42.             "org.apache.catalina.LifecycleListener");   
  43.   
  44.     digester.addObjectCreate("Server/Service/Executor", "org.apache.catalina.core.StandardThreadExecutor", "className");   
  45.     digester.addSetProperties("Server/Service/Executor");   
  46.   
  47.     digester.addSetNext("Server/Service/Executor", "addExecutor", "org.apache.catalina.Executor");   
  48.   
  49.     digester.addRule("Server/Service/Connector", new ConnectorCreateRule());   
  50.     digester.addRule("Server/Service/Connector", new SetAllPropertiesRule(new String[] { "executor" }));   
  51.     digester.addSetNext("Server/Service/Connector", "addConnector",   
  52.             "org.apache.catalina.connector.Connector");   
  53.   
  54.     digester.addObjectCreate("Server/Service/Connector/Listener", null, "className");   
  55.     digester.addSetProperties("Server/Service/Connector/Listener");   
  56.     digester.addSetNext("Server/Service/Connector/Listener", "addLifecycleListener",   
  57.             "org.apache.catalina.LifecycleListener");   
  58.   
  59.     digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));   
  60.     digester.addRuleSet(new EngineRuleSet("Server/Service/"));   
  61.     digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));   
  62.     digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));   
  63.     digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Host/Cluster/"));   
  64.     digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));   
  65.   
  66.     digester.addRule("Server/Service/Engine", new SetParentClassLoaderRule(parentClassLoader));   
  67.     digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Cluster/"));   
  68.   
  69.     long t2 = System.currentTimeMillis();   
  70.     if (log.isDebugEnabled())   
  71.         log.debug("Digester for server.xml created " + (t2 - t1));   
  72.     return (digester);   
  73.   
  74. }  

protected Digester createStartDigester() { long t1 = System.currentTimeMillis(); // 初始化digester Digester digester = new Digester(); digester.setValidating(false); digester.setRulesValidation(true); HashMap<Class, List<String>> fakeAttributes = new HashMap<Class, List<String>>(); ArrayList<String> attrs = new ArrayList<String>(); attrs.add("className"); fakeAttributes.put(Object.class, attrs); digester.setFakeAttributes(fakeAttributes); digester.setClassLoader(StandardServer.class.getClassLoader()); // 三个参数分别为:1. xml标签的名字;2. 默认的Java类名;3.如果标签中有这个属性,那么它就覆盖掉默认的Java类名 // 具体到下边的这条语句,就是处理"Server"标签,并实例化一个StandardServer类的实例 // 如果Server标签有一个叫className的属性,就会覆盖掉默认的Java类型。 digester.addObjectCreate("Server", "org.apache.catalina.core.StandardServer", "className"); // 设定一个SetPropertiesRule,这个规则是用于堆栈顶端元素的属性设置 digester.addSetProperties("Server"); // 三个参数分别为:1.xml标签名;2.要设定的"父对象"(与继承无关)的方法名;3.方法参数的Java类型 digester.addSetNext("Server", "setServer", "org.apache.catalina.Server"); digester.addObjectCreate("Server/GlobalNamingResources", "org.apache.catalina.deploy.NamingResources"); digester.addSetProperties("Server/GlobalNamingResources"); digester.addSetNext("Server/GlobalNamingResources", "setGlobalNamingResources", "org.apache.catalina.deploy.NamingResources"); digester.addObjectCreate("Server/Listener", null, "className"); digester.addSetProperties("Server/Listener"); digester.addSetNext("Server/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); digester.addObjectCreate("Server/Service", "org.apache.catalina.core.StandardService", "className"); digester.addSetProperties("Server/Service"); digester.addSetNext("Server/Service", "addService", "org.apache.catalina.Service"); digester.addObjectCreate("Server/Service/Listener", null, "className"); digester.addSetProperties("Server/Service/Listener"); digester.addSetNext("Server/Service/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); digester.addObjectCreate("Server/Service/Executor", "org.apache.catalina.core.StandardThreadExecutor", "className"); digester.addSetProperties("Server/Service/Executor"); digester.addSetNext("Server/Service/Executor", "addExecutor", "org.apache.catalina.Executor"); digester.addRule("Server/Service/Connector", new ConnectorCreateRule()); digester.addRule("Server/Service/Connector", new SetAllPropertiesRule(new String[] { "executor" })); digester.addSetNext("Server/Service/Connector", "addConnector", "org.apache.catalina.connector.Connector"); digester.addObjectCreate("Server/Service/Connector/Listener", null, "className"); digester.addSetProperties("Server/Service/Connector/Listener"); digester.addSetNext("Server/Service/Connector/Listener", "addLifecycleListener", "org.apache.catalina.LifecycleListener"); digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/")); digester.addRuleSet(new EngineRuleSet("Server/Service/")); digester.addRuleSet(new HostRuleSet("Server/Service/Engine/")); digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/")); digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Host/Cluster/")); digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/")); digester.addRule("Server/Service/Engine", new SetParentClassLoaderRule(parentClassLoader)); digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Cluster/")); long t2 = System.currentTimeMillis(); if (log.isDebugEnabled()) log.debug("Digester for server.xml created " + (t2 - t1)); return (digester); }

虽然没有研究Digester,但是大致的过程还是可以猜出来的,首先,Digester需要一个堆栈的顶端元素,在Catalina#load()里压入了Catalina类本身,后边会介绍到,然后会根据一系列addObjectCreate,addSetProperties,addSetNext设定类与xml的绑定等。比如GlobalNamingResources这个属性,

Java代码 Tomcat启动部分源代码分析(三) -- 载入 - guoyang1982 - 游龙

  1. digester.addObjectCreate("Server/GlobalNamingResources", "org.apache.catalina.deploy.NamingResources");   
  2. digester.addSetProperties("Server/GlobalNamingResources");   
  3. digester.addSetNext("Server/GlobalNamingResources", "setGlobalNamingResources", "org.apache.catalina.deploy.NamingResources");  

digester.addObjectCreate("Server/GlobalNamingResources", "org.apache.catalina.deploy.NamingResources");digester.addSetProperties("Server/GlobalNamingResources");digester.addSetNext("Server/GlobalNamingResources", "setGlobalNamingResources", "org.apache.catalina.deploy.NamingResources");

上边的3条语句设定了遇到Server/GlobalNamingResources,实例化一个NamingResources类的对象,并调用setGlobalNamingResources将这个对象与父对象关联。而它的父对象很明显就是"Server"定义的对象,就是StandardServer类的对象。而StandardServer又与栈定对象相关联(通过调用Catalina的#setServer设定的)。所以解析完server.xml之后,Catalina的成员变量"server(定义为:protected Server server = null;)"就应该被赋值了,并且xml中的所有元素在server下边都有对应的对象相关联。

这里有必要介绍下server.xml中定义的各个元素的作用(引用自http://jackycheng2007.javaeye.com/blog/188401)

Server

"Server" 是单例的,代表整个JVM,它可能包含几个"Service"实例。 "Server" 从指定的端口监听关闭命令。

<Server port="8005" shutdown="SHUTDOWN">

"Service"

一个"Service"是一个或者多个"Connectors"的集合,他们共享一个"Container"(所以多个web应用在整个容器内是可见的)。通常但不必须,Container是一个"Engine"。

<Service name="Catalina">

可以把Service看成媒介,它存活在一个Server里面,把一个或几个Connectors绑定在一个Engine上。

所以,在server.xml 中"Service"是Server的子组件。Connector 和 Engine 是Service的子组件。

"Connector"

一个Connector将在某个指定端口上侦听客户请求,并将获得的请求交给Engine来处理,从Engine处获得回应并返回客户

TOMCAT有两个典型的Connector,一个直接侦听来自browser的http请求,一个侦听来自其它WebServer的请求

Coyote Http/1.1 Connector 在端口8080处侦听来自客户browser的http请求

Coyote JK2 Connector 在端口8009处侦听来自其它WebServer(Apache)的servlet/jsp代理请求.

<Connector port="8080" protocol="HTTP/1.1" maxThreads="150" connectionTimeout="20000" redirectPort="8443" />

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

"Engine"

一个"Engine"代表了一个service的请求管道。一个service可能有多个Connector, 这个Engine接收并处理来自这些Connector的请求(requests ),并且将处理反馈(response )传给相应的connector,进而传给客户端。

"Host "

一个Host 是域名(e.g. www.yourcompany.com)和tomcat server的联系体。 一个Engine可以包含多个Host,而且Host 可以支持网络别名如yourcompany.com 和 abc.yourcompany.com。所以,Host是Engine的子组件。

"Context"

一个Context代表一个web应用。一个Host可以包含多个 Context, 他们都有一个唯一的路径。

再回到代码。

digester初始化结束后,就是一系列的server.xml的寻找工作了,当定位了server.xml之后,就要开始对它的解析了。

Java代码 Tomcat启动部分源代码分析(三) -- 载入 - guoyang1982 - 游龙

  1. try {   
  2.     inputSource.setByteStream(inputStream);   
  3.     digester.push(this);   
  4.     digester.parse(inputSource);   
  5.     inputStream.close();   
  6. } catch (Exception e) {   
  7.     log.warn("Catalina.start using " + getConfigFile() + ": ", e);   
  8.     return;   
  9. }  

try { inputSource.setByteStream(inputStream); digester.push(this); digester.parse(inputSource); inputStream.close(); } catch (Exception e) { log.warn("Catalina.start using " + getConfigFile() + ": ", e); return; }

这一段就是解析的代码,很明显,digester把Catalina对象压到了栈顶。

然后,调用了这样的一句话:server.initialize();前面已经提到过了,server对象已经被实力化为StandardServer类的对象,那么看一下StandardServer#initialize()都做了什么:

Java代码 Tomcat启动部分源代码分析(三) -- 载入 - guoyang1982 - 游龙

  1. public void initialize() throws LifecycleException {   
  2.     if (initialized) {   
  3.         log.info(sm.getString("standardServer.initialize.initialized"));   
  4.         return;   
  5.     }   
  6.   
  7.     // 通知所有Lifecycle事件监听器"INIT_EVENT"事件的发生   
  8.     lifecycle.fireLifecycleEvent(INIT_EVENT, null);   
  9.     initialized = true;   
  10.   
  11.     // JMX相关的配置   
  12.     if (oname == null) {   
  13.         try {   
  14.             oname = new ObjectName("Catalina:type=Server");   
  15.             Registry.getRegistry(null, null).registerComponent(this, oname, null);   
  16.         } catch (Exception e) {   
  17.             log.error("Error registering ", e);   
  18.         }   
  19.     }   
  20.   
  21.     try {   
  22.         ObjectName oname2 = new ObjectName(oname.getDomain() + ":type=StringCache");   
  23.         Registry.getRegistry(null, null).registerComponent(new StringCache(), oname2, null);   
  24.     } catch (Exception e) {   
  25.         log.error("Error registering ", e);   
  26.     }   
  27.   
  28.     // Service初始化,默认只有一个org.apache.catalina.core.StandardService实例   
  29.     // 见Catalina#createStartDigester()   
  30.     for (int i = 0; i < services.length; i++) {   
  31.         services[i].initialize();   
  32.     }   
  33. }  

public void initialize() throws LifecycleException { if (initialized) { log.info(sm.getString("standardServer.initialize.initialized")); return; } // 通知所有Lifecycle事件监听器"INIT_EVENT"事件的发生 lifecycle.fireLifecycleEvent(INIT_EVENT, null); initialized = true; // JMX相关的配置 if (oname == null) { try { oname = new ObjectName("Catalina:type=Server"); Registry.getRegistry(null, null).registerComponent(this, oname, null); } catch (Exception e) { log.error("Error registering ", e); } } try { ObjectName oname2 = new ObjectName(oname.getDomain() + ":type=StringCache"); Registry.getRegistry(null, null).registerComponent(new StringCache(), oname2, null); } catch (Exception e) { log.error("Error registering ", e); } // Service初始化,默认只有一个org.apache.catalina.core.StandardService实例 // 见Catalina#createStartDigester() for (int i = 0; i < services.length; i++) { services[i].initialize(); } }

首先,lifecycle.fireLifecycleEvent(INIT_EVENT, null);通知了StandardServer包含的事件监听器有一个"INIT_EVENT"事件到来了,默认有如下四个监听器:

org.apache.catalina.core.AprLifecycleListener)(Apache Portable Runtime -- APR)

org.apache.catalina.core.JasperListener(Java Server Pages -- JSP)

org.apache.catalina.mbeans.ServerLifecycleListener

org.apache.catalina.mbeans.GlobalResourcesLifecycleListener

四个监听器的INIT_EVENT方法处理最后涉及到了native方法的调用,就不再详细说了。

然后,对JMX进行了初始化,JMX暂时不懂。

最后,对Service进行了初始化,默认只有一个StandardService#initialize()

Java代码 Tomcat启动部分源代码分析(三) -- 载入 - guoyang1982 - 游龙

  1. public void initialize() throws LifecycleException {   
  2.     if (initialized) {   
  3.         if (log.isInfoEnabled())   
  4.             log.info(sm.getString("standardService.initialize.initialized"));   
  5.         return;   
  6.     }   
  7.     initialized = true;   
  8.   
  9.     if (oname == null) {   
  10.         try {   
  11.             // 容器   
  12.             Container engine = this.getContainer();   
  13.             // 名字,默认是Catalina   
  14.             domain = engine.getName();   
  15.             oname = new ObjectName(domain + ":type=Service,serviceName=" + name);   
  16.             this.controller = oname;   
  17.             // 注册JMX,我发誓看完这个就去看JMX   
  18.             Registry.getRegistry(null, null).registerComponent(this, oname, null);   
  19.                
  20.             // Executors的注册   
  21.             Executor[] executors = findExecutors();   
  22.             for (int i = 0; i < executors.length; i++) {   
  23.                 ObjectName executorObjectName = new ObjectName(domain + ":type=Executor,name="  
  24.                         + executors[i].getName());   
  25.                 Registry.getRegistry(null, null).registerComponent(executors[i],   
  26.                         executorObjectName, null);   
  27.             }   
  28.   
  29.         } catch (Exception e) {   
  30.             log.error(sm.getString("standardService.register.failed", domain), e);   
  31.         }   
  32.   
  33.     }   
  34.     if (server == null) {   
  35.         ServerFactory.getServer().addService(this);   
  36.     }   
  37.   
  38.     synchronized (connectors) {   
  39.         // 这里是Connector的初始化,默认有HTTP/1.1(8080),AJP/1.3(8009)两个   
  40.         // <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />   
  41.         // <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />   
  42.         for (int i = 0; i < connectors.length; i++) {   
  43.             // ServerSocket初始化   
  44.             connectors[i].initialize();   
  45.         }   
  46.     }   
  47. }  

public void initialize() throws LifecycleException { if (initialized) { if (log.isInfoEnabled()) log.info(sm.getString("standardService.initialize.initialized")); return; } initialized = true; if (oname == null) { try { // 容器 Container engine = this.getContainer(); // 名字,默认是Catalina domain = engine.getName(); oname = new ObjectName(domain + ":type=Service,serviceName=" + name); this.controller = oname; // 注册JMX,我发誓看完这个就去看JMX Registry.getRegistry(null, null).registerComponent(this, oname, null); // Executors的注册 Executor[] executors = findExecutors(); for (int i = 0; i < executors.length; i++) { ObjectName executorObjectName = new ObjectName(domain + ":type=Executor,name=" + executors[i].getName()); Registry.getRegistry(null, null).registerComponent(executors[i], executorObjectName, null); } } catch (Exception e) { log.error(sm.getString("standardService.register.failed", domain), e); } } if (server == null) { ServerFactory.getServer().addService(this); } synchronized (connectors) { // 这里是Connector的初始化,默认有HTTP/1.1(8080),AJP/1.3(8009)两个 // <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> // <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> for (int i = 0; i < connectors.length; i++) { // ServerSocket初始化 connectors[i].initialize(); } } }

通过上述的步骤,Tomcat的ServerSocket已经建立了起来,load的过程也结束了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值