synchronized (daemonLock) { if (daemon == null) { //初始化一个启动器 Bootstrapbootstrap=newBootstrap(); try { //创建了catalina实例,并且赋值给了catalinaDaemon变量 bootstrap.init(); } catch (Throwable t) { handleThrowable(t); t.printStackTrace(); return; } daemon = bootstrap; } else { // When running as a service the call to stop will be on a new // thread so make sure the correct class loader is used to // prevent a range of class not found exceptions. Thread.currentThread().setContextClassLoader(daemon.catalinaLoader); } }
// 注册关闭钩爪代码 if (useShutdownHook) { if (shutdownHook == null) { shutdownHook = newCatalinaShutdownHook(); } Runtime.getRuntime().addShutdownHook(shutdownHook);
// If JULI is being used, disable JULI's shutdown hook since // shutdown hooks run in parallel and log messages may be lost // if JULI's hook completes before the CatalinaShutdownHook() LogManagerlogManager= LogManager.getLogManager(); if (logManager instanceof ClassLoaderLogManager) { ((ClassLoaderLogManager) logManager).setUseShutdownHook( false); } } //更加await的值确定是否进入等待状态 if (await) { await(); stop(); } }
synchronized (servicesLock) { for (inti=0; i < services.length; i++) { services[i].start(); } }
Service的启动过程
Service的默认实现是org.apache.catalina.core.StandardService, class StandardService extends LifecycleMBeanBase implements Service 它同样也是继承自LifecycleMBeanBase类的,所以init和start方法最终就会调用initInternal和startInternal方法。 这两个方法的具体实现如下:
// Start our defined Connectors second synchronized (connectorsLock) { for (Connector connector: connectors) { // If it has already failed, don't try and start it if (connector.getState() != LifecycleState.FAILED) { connector.start(); } } } }
try { setStateInternal(LifecycleState.STARTING_PREP, null, false); //调用相应的模板方法 startInternal(); if (state.equals(LifecycleState.FAILED)) { // This is a 'controlled' failure. The component put itself into the // FAILED state so call stop() to complete the clean-up. stop(); } elseif (!state.equals(LifecycleState.STARTING)) { // Shouldn't be necessary but acts as a check that sub-classes are // doing what they are supposed to. invalidTransition(Lifecycle.AFTER_START_EVENT); } else { setStateInternal(LifecycleState.STARTED, null, false); } } catch (Throwable t) { // This is an 'uncontrolled' failure so put the component into the // FAILED state and throw an exception. handleSubClassException(t, "lifecycleBase.startFail", toString()); } }
//如果已经通过构造方法设置了webApplicationContext if (this.webApplicationContext != null) { // A context instance was injected at construction time -> use it wac = this.webApplicationContext; if (wac instanceof ConfigurableWebApplicationContext) { ConfigurableWebApplicationContextcwac= (ConfigurableWebApplicationContext) wac; if (!cwac.isActive()) { // The context has not yet been refreshed -> provide services such as // setting the parent context, setting the application context id, etc if (cwac.getParent() == null) { // The context instance was injected without an explicit parent -> set // the root application context (if any; may be null) as the parent cwac.setParent(rootContext); } configureAndRefreshWebApplicationContext(cwac); } } } if (wac == null) { // No context instance was injected at construction time -> see if one // has been registered in the servlet context. If one exists, it is assumed // that the parent context (if any) has already been set and that the // user has performed any initialization such as setting the context id //当webApplicationContext已经存在ServletContext中时, //通过配置在Servlet中的contextAttribute参数获取 wac = findWebApplicationContext(); } if (wac == null) { // No context instance is defined for this servlet -> create a local one //如果webApplicationContext还没看有创建,则创建一个 wac = createWebApplicationContext(rootContext); }
if (!this.refreshEventReceived) { // Either the context is not a ConfigurableApplicationContext with refresh // support or the context injected at construction time had already been // refreshed -> trigger initial onRefresh manually here. //当contextRefreshedEvent事件没有触发时调用此模板方法 onRefresh(wac); }
if (this.publishContext) { // Publish the context as a servlet context attribute. //将ApplicatinoContext保存到ServletContext中 StringattrName= getServletContextAttributeName(); getServletContext().setAttribute(attrName, wac); if (this.logger.isDebugEnabled()) { this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() + "' as ServletContext attribute with name [" + attrName + "]"); } }