image。pngTomcat的启动核心流程 前面给大家介绍了Tomcat中的生命周期的设计,掌握了这块对于我们分析Tomcat的核心流程是非常有帮助的,也就是我们需要创建相关的核心组件,比如Server,Service肯定都绕不开生命周期的方法。 image。png1。启动的入口 你可以通过脚本来启动Tomcat服务(startup。bat),但如果你看过脚本的命令,你会发现最终调用的还是Bootstrap中的main方法,所以我们需要从main方法来开始 image。png 然后我们去看main方法中的代码,我们需要重点关注的方法有三个bootstrap。init()方法load()方法start()方法 也就是在这三个方法中会完成Tomcat的核心操作。2。init方法 我们来看下init方法中的代码,非核心的我们直接去掉publicvoidinit()throwsException{创建相关的类加载器initClassLoaders();省略部分代码。。。通过反射创建了Catalina类对象Classlt;?startupClasscatalinaLoader。loadClass(org。apache。catalina。startup。Catalina);创建了Catalina实例ObjectstartupInstancestartupClass。getConstructor()。newInstance();省略部分代码。。。StringmethodNamesetParentClassLoader;Classlt;?paramTypes〔〕newClass〔1〕;paramTypes〔0〕Class。forName(java。lang。ClassLoader);ObjectparamValues〔〕newObject〔1〕;paramValues〔0〕sharedLoader;把sharedLoader设置为了commonLoader的父加载器MethodmethodstartupInstance。getClass()。getMethod(methodName,paramTypes);method。invoke(startupInstance,paramValues);Catalina实例赋值给了catalinaDaemoncatalinaDaemonstartupInstance;}首先是调用了initClassLoaders()方法,这个方法会完成对应的ClassLoader的创建,这个比较重要,后面专门写一篇文章来介绍。通过反射的方式创建了Catalina的类对象,并通过反射创建了Catalina的实例设置了类加载器的父子关系用过成员变量catalinaDaemon记录了我们创建的Catalina实例 这个是通过bootstrap。init()方法我们可以获取到的有用的信息。然后我们继续往下面看。3。load方法 然后我们来看下load方法做了什么事情,代码如下:privatevoidload(String〔〕arguments)throwsException{Calltheload()methodStringmethodNameload;load方法的名称Objectparam〔〕;Classlt;?paramTypes〔〕;if(argumentsnullarguments。length0){paramTypesnull;paramnull;}else{paramTypesnewClass〔1〕;paramTypes〔0〕arguments。getClass();paramnewObject〔1〕;param〔0〕arguments;}catalinaDaemon就是在init中创建的Catalina对象MethodmethodcatalinaDaemon。getClass()。getMethod(methodName,paramTypes);if(log。isDebugEnabled()){log。debug(Callingstartupclassmethod);}会执行Catalina的load方法method。invoke(catalinaDaemon,param);} 上面的代码非常简单,通过注释我们也可以看出该方法的作用是调用Catalina的load方法。所以我们还需要加入到Catalina的load方法中来查看,代码同样比较长,只留下关键代码publicvoidload(){if(loaded){return;只能被加载一次}loadedtrue;initDirs();废弃的方法BeforedigesteritmaybeneededinitNaming();和JNDI相关的内容忽略CreateandexecuteourDigester创建并且执行我们的Digester对象Server。xmlDigesterdigestercreateStartDigester();省略掉了Digester文件处理的代码getServer()。setCatalina(this);Server对象绑定Catalina对象getServer()。setCatalinaHome(Bootstrap。getCatalinaHomeFile());getServer()。setCatalinaBase(Bootstrap。getCatalinaBaseFile());StreamredirectioninitStreams();省略掉了部分代码。。。getServer()。init();完成ServerServiceEngineConnector等组件的init操作} 把上面的代码简化后我们发现这个Load方法其实也是蛮简单的,就做了两件事。通过Apache下的Digester组件完成了Server。xml文件的解析通过getServer()。init()方法完成了Server,Service,Engin,Connector等核心组件的初始化操作,这块和前面的LifecycleBase呼应起来了。 image。png 如果生命周期的内容不清楚,请看上一篇文章的介绍。4。start方法 最后我们来看下start方法的代码。publicvoidstart()throwsException{if(catalinaDaemonnull){init();如果catalinaDaemon为空初始化操作}获取的是Catalina中的start方法MethodmethodcatalinaDaemon。getClass()。getMethod(start,(Class〔〕)null);执行Catalina的start方法method。invoke(catalinaDaemon,(Object〔〕)null);} 上面的代码逻辑也很清楚,就是通过反射的方式调用了Catalina对象的start方法。所以进入Catalina的start方法中查看。publicvoidstart(){if(getServer()null){load();如果Server为空重新init相关的组件}if(getServer()null){log。fatal(Cannotstartserver。Serverinstanceisnotconfigured。);return;}Startthenewserver关键方法启动Servertry{getServer()。start();}catch(LifecycleExceptione){省略。。。}省略。。。Registershutdownhook注册关闭的钩子if(useShutdownHook){省略。。。}if(await){await();stop();}} 通过上面的代码我们可以发现核心的代码还是getServer。start()方法,也就是通过Server对象来嵌套的调用相关注解的start方法。 image。png5。核心流程的总结 我们可以通过下图来总结下Tomcat启动的核心流程 image。png 从图中我们可以看到Bootstrap其实没有做什么核心的事情,主要还是Catalina来完成的。 本文只是从Tomcat的启动核心流程来讲解,还有些具体的实现细节没有介绍到,会在后续的文章中给大家细细到来,欢迎关注收藏哦!