一、Tomcat的启动核心流程
前面给大家介绍了Tomcat中的生命周期的设计,掌握了这块对于我们分析Tomcat的核心流程是非常有帮助的,也就是我们需要创建相关的核心组件,比如Server,Service肯定都绕不开生命周期的方法。
1.启动的入口
你可以通过脚本来启动Tomcat服务(startup.bat),但如果你看过脚本的命令,你会发现最终调用的还是Bootstrap中的main方法,所以我们需要从main方法来开始
然后我们去看main方法中的代码,我们需要重点关注的方法有三个
- bootstrap.init()方法
- load()方法
- start()方法
也就是在这三个方法中会完成Tomcat的核心操作。
2.init方法
我们来看下init方法中的代码,非核心的我们直接去掉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public void init() throws Exception { // 创建相关的类加载器 initClassLoaders(); // 省略部分代码... // 通过反射创建了 Catalina 类对象 Class<?> startupClass = catalinaLoader .loadClass( "org.apache.catalina.startup.Catalina" ); // 创建了 Catalina 实例 Object startupInstance = startupClass.getConstructor().newInstance(); // 省略部分代码... String methodName = "setParentClassLoader" ; Class<?> paramTypes[] = new Class[ 1 ]; paramTypes[ 0 ] = Class.forName( "java.lang.ClassLoader" ); Object paramValues[] = new Object[ 1 ]; paramValues[ 0 ] = sharedLoader; // 把 sharedLoader 设置为了 commonLoader的父加载器 Method method = startupInstance.getClass().getMethod(methodName, paramTypes); method.invoke(startupInstance, paramValues); // Catalina 实例 赋值给了 catalinaDaemon catalinaDaemon = startupInstance; } |
- 首先是调用了initClassLoaders()方法,这个方法会完成对应的ClassLoader的创建,这个比较重要,后面专门写一篇文章来介绍。
- 通过反射的方式创建了Catalina的类对象,并通过反射创建了Catalina的实例
- 设置了类加载器的父子关系
- 用过成员变量catalinaDaemon记录了我们创建的Catalina实例
这个是通过bootstrap.init()方法我们可以获取到的有用的信息。然后我们继续往下面看。
3.load方法
然后我们来看下load方法做了什么事情,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | private void load(String[] arguments) throws Exception { // Call the load() method String methodName = "load" ; // 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; } // catalinaDaemon 就是在 init中创建的 Catalina 对象 Method method = catalinaDaemon.getClass().getMethod(methodName, paramTypes); if (log.isDebugEnabled()) { log.debug( "Calling startup class " + method); } // 会执行 Catalina的load方法 method.invoke(catalinaDaemon, param); } |
上面的代码非常简单,通过注释我们也可以看出该方法的作用是调用 Catalina的load方法。所以我们还需要加入到Catalina的load方法中来查看,代码同样比较长,只留下关键代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public void load() { if (loaded) { return ; // 只能被加载一次 } loaded = true ; initDirs(); // 废弃的方法 // Before digester - it may be needed initNaming(); // 和JNDI 相关的内容 忽略 // Create and execute our Digester // 创建并且执行我们的 Digester 对象 Server.xml Digester digester = createStartDigester(); // 省略掉了 Digester文件处理的代码 getServer().setCatalina( this ); // Server对象绑定 Catalina对象 getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile()); getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile()); // Stream redirection initStreams(); // 省略掉了部分代码... getServer().init(); // 完成 Server Service Engine Connector等组件的init操作 } |
把上面的代码简化后我们发现这个Load方法其实也是蛮简单的,就做了两件事。
- 通过Apache下的Digester组件完成了Server.xml文件的解析
- 通过getServer().init() 方法完成了Server,Service,Engin,Connector等核心组件的初始化操作,这块和前面的LifecycleBase呼应起来了。
如果生命周期的内容不清楚,请看前面内容介绍
4.start方法
最后我们来看下start方法的代码。
1 2 3 4 5 6 7 8 9 | public void start() throws Exception { if (catalinaDaemon == null ) { init(); // 如果 catalinaDaemon 为空 初始化操作 } // 获取的是 Catalina 中的 start方法 Method method = catalinaDaemon.getClass().getMethod( "start" , (Class []) null ); // 执行 Catalina 的start方法 method.invoke(catalinaDaemon, (Object []) null ); } |
上面的代码逻辑也很清楚,就是通过反射的方式调用了Catalina对象的start方法。所以进入Catalina的start方法中查看。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public void start() { if (getServer() == null ) { load(); // 如果Server 为空 重新 init 相关的组件 } if (getServer() == null ) { log.fatal( "Cannot start server. Server instance is not configured." ); return ; } // Start the new server 关键方法--->启动Server try { getServer().start(); } catch (LifecycleException e) { // 省略... } // 省略... // Register shutdown hook 注册关闭的钩子 if (useShutdownHook) { // 省略... } if (await) { await(); stop(); } } |
通过上面的代码我们可以发现核心的代码还是getServer.start()方法,也就是通过Server对象来嵌套的调用相关注解的start方法。
5.核心流程的总结
我们可以通过下图来总结下Tomcat启动的核心流程
从图中我们可以看到Bootstrap其实没有做什么核心的事情,主要还是Catalina来完成的。
以上就是Tomcat启动核心流程示例详解的详细内容,更多关于Tomcat启动流程的资料请关注IT俱乐部其它相关文章!