tomcat源码分析二

接着分析下start()方法:

Catalina.start() {...
if (getServer() == null) {
            load();
 getServer().start();...
}
StandardServer.startInternal(){
        fireLifecycleEvent(CONFIGURE_START_EVENT, null);
        setState(LifecycleState.STARTING);//设置Server状态 触发lisener监听器
        globalNamingResources.start();
        // Start our defined Services
        synchronized (servicesLock) {
            for (int i = 0; i < services.length; i++) {
                services[i].start();
            }
        }
}
StandardService.startInternal(){...
setState(LifecycleState.STARTING);
engine.start();
executor.start();
mapperListener.start();//组件添加能监听到
synchronized (connectorsLock) {
   for (Connector connector: connectors) {
      try {
         // If it has already failed, don't try and start it
         if (connector.getState() != LifecycleState.FAILED) {
         connector.start();...
}

我们看下engine的启动

StandardEngine.startInternal(){
super.startInternal();//ContainerBase...
}
ContainerBase.startInternal(){...
        Cluster cluster = getClusterInternal();
        if (cluster instanceof Lifecycle) {
            ((Lifecycle) cluster).start();
        }
        Realm realm = getRealmInternal();
        if (realm instanceof Lifecycle) {
            ((Lifecycle) realm).start();
        }
        Container children[] = findChildren();
        List<Future<Void>> results = new ArrayList<>();
        for (int i = 0; i < children.length; i++) {
            results.add(startStopExecutor.submit(new StartChild(children[i])));//启动子节点
        }
        MultiThrowable multiThrowable = null;
        for (Future<Void> result : results) {
            try {
                result.get();//完成了所有子组件的启动
            } catch (Throwable e) {
                log.error(sm.getString("containerBase.threadedStartFailed"), e);...
        if (pipeline instanceof Lifecycle) {// Start the Valves in our pipeline (including the basic), if any
            ((Lifecycle) pipeline).start();//把请求给到容易后通过value(类似阀门),然后责任链形式匹配容器上的value。容器就拿到了这个请求
        }
        setState(LifecycleState.STARTING);
        threadStart();// Start our thread
...}
StandardHost.startInternal(){...
String errorValve = getErrorReportValveClass();// Set error report valve
super.startInternal();//Container
}
ContainerBase.startInternal(){...
setState(LifecycleState.STARTING);//激发监听器HostConfig
}

host启动

HostConfig.start() {...
if (host.getDeployOnStartup())
            deployApps();//部署app
...}
deployApps() {
    File appBase = host.getAppBaseFile();
    File configBase = host.getConfigBaseFile();
    // 过滤出 webapp 要部署应用的目录
    String[] filteredAppPaths = filterAppPaths(appBase.list());
    // 部署 xml 描述文件
    deployDescriptors(configBase, configBase.list());
    // 解压 war 包,但是这里还不会去启动应用
    deployWARs(appBase, filteredAppPaths);
    // 处理已经存在的目录,前面解压的 war 包不会再行处理
    deployDirectories(appBase, filteredAppPaths);
}
deployDirectory(ContextName cn, File dir) {...
    context.setName(cn.getName());
    context.setPath(cn.getPath());
    context.setWebappVersion(cn.getVersion());
    context.setDocBase(cn.getBaseName());
    host.addChild(context);
...}

context启动

StandardContext.startInternal(){...
// Send j2ee.state.starting notification
        if (this.getObjectName() != null) {
            Notification notification = new Notification("j2ee.state.starting",
                    this.getObjectName(), sequenceNumber.getAndIncrement());
            broadcaster.sendNotification(notification);
        }...
    postWorkDirectory();// Post work directory 配置工作目录
    fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);// Notify our interested LifecycleListeners 触发ContextConfig
...}
ContextConfig.webConfig() {...
        WebXmlParser webXmlParser = new WebXmlParser(context.getXmlNamespaceAware(),
                context.getXmlValidation(), context.getXmlBlockExternal());
        Set<WebXml> defaults = new HashSet<>();
        defaults.add(getDefaultWebXmlFragment(webXmlParser));
        WebXml webXml = createWebXml();     
        InputSource contextWebXml = getContextWebXmlSource();// Parse context level web.xml
        if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) {
            ok = false;
        }...
        // Step 1. Identify all the JARs packaged with the application and those
        // provided by the container. If any of the application JARs have a
        // web-fragment.xml it will be parsed at this point. web-fragment.xml
        // files are ignored for container provided JARs.
        Map<String,WebXml> fragments = processJarsForWebFragments(webXml, webXmlParser);
        // Step 2. Order the fragments.
        Set<WebXml> orderedFragments = null;
        orderedFragments =
                WebXml.orderWebFragments(webXml, fragments, sContext);
        // Step 3. Look for ServletContainerInitializer implementations
        if (ok) {
            processServletContainerInitializers();
        }
        if  (!webXml.isMetadataComplete() || typeInitializerMap.size() > 0) {
            // Steps 4 & 5.
            processClasses(webXml, orderedFragments);//没有配置时,里面有处理注解式(servelt3)的
        }
if (!webXml.isMetadataComplete()) {
            // Step 6. Merge web-fragment.xml files into the main web.xml
            // file.
            if (ok) {
                ok = webXml.merge(orderedFragments);
            }
            // Step 7. Apply global defaults
            // Have to merge defaults before JSP conversion since defaults
            // provide JSP servlet definition.
            webXml.merge(defaults);
            // Step 8. Convert explicitly mentioned jsps to servlets
            if (ok) {
                convertJsps(webXml);
            }
            // Step 9. Apply merged web.xml to Context
            if (ok) {
                configureContext(webXml);
            }
...}
processAnnotationsWebResource() {...
processAnnotationsStream(is, fragment, handlesTypesOnly, javaClassCache);
...}
processAnnotationsStream{...
 ClassParser parser = new ClassParser(is);//解析,并没有立刻加载到jvm,使用的时候在加载
        JavaClass clazz = parser.parse();
        checkHandlesTypes(clazz, javaClassCache);
        if (handlesTypesOnly) {
            return;
        }
        processClass(fragment, clazz);
...}
configureContext(){...
for (FilterMap filterMap : webxml.getFilterMappings()) {
            context.addFilterMap(filterMap);
        }
        context.setJspConfigDescriptor(webxml.getJspConfigDescriptor());
        for (String listener : webxml.getListeners()) {
            context.addApplicationListener(listener);
        }...
context.addChild(wrapper);//line 1380 添加了wrapper(servlet)
...}
StandardContext.startInternal(){...
// Start our child containers, if not already started
      for (Container child : findChildren()) {
         if (!child.getState().isAvailable()) {
             child.start();
         }
      }
...}

后续severlet的加载,优先级 warpper load方法等:


容器组件启动会触发lisener监听器从而知道容器中发生了变化(如:热部署)。

原文地址:https://www.cnblogs.com/leifonlyone/p/12752595.html