Tomcat8.5源码分析-StandardContext

来源:互联网 发布:java计算天干地支 编辑:程序博客网 时间:2024/05/22 00:08

StandardContext

直接看代码,相关操作已经打上注释:

protected synchronized void startInternal() throws LifecycleException {        if(log.isDebugEnabled())            log.debug("Starting " + getBaseName());        // Send j2ee.state.starting notification        //发送正在启动的通知        if (this.getObjectName() != null) {            Notification notification = new Notification("j2ee.state.starting",                    this.getObjectName(), sequenceNumber.getAndIncrement());            broadcaster.sendNotification(notification);        }        setConfigured(false);        boolean ok = true;        // Currently this is effectively a NO-OP but needs to be called to        // ensure the NamingResources follows the correct lifecycle        //启动context维护的JNDI资源        if (namingResources != null) {            namingResources.start();        }        // Add missing components as necessary        if (getResources() == null) {   // (1) Required by Loader            if (log.isDebugEnabled())                log.debug("Configuring default Resources");            try {                setResources(new StandardRoot(this));//初始化当前的webResourceRoot            } catch (IllegalArgumentException e) {                log.error(sm.getString("standardContext.resourcesInit"), e);                ok = false;            }        }        if (ok) {            resourcesStart();//启动当前的webRecourseRoot,主要用于类加载和按照路径查找资源文件        }        //创建web应用加载器        if (getLoader() == null) {            WebappLoader webappLoader = new WebappLoader(getParentClassLoader());            webappLoader.setDelegate(getDelegate());            setLoader(webappLoader);        }        // An explicit cookie processor hasn't been specified; use the default        //如果没有指定一个明确的cookie,使用默认的        if (cookieProcessor == null) {            cookieProcessor = new Rfc6265CookieProcessor();        }        // Initialize character set mapper        //初始化字符集映射        getCharsetMapper();        // Post work directory        //传递工作目录        postWorkDirectory();        // Validate required extensions        boolean dependencyCheck = true;        try {            dependencyCheck = ExtensionValidator.validateApplication                (getResources(), this);        } catch (IOException ioe) {            log.error(sm.getString("standardContext.extensionValidationError"), ioe);            dependencyCheck = false;        }        //web应用的依赖检测,主要用来检测依赖拓展点的完整性        if (!dependencyCheck) {            // do not make application available if dependency check fails            ok = false;        }        // Reading the "catalina.useNaming" environment variable        String useNamingProperty = System.getProperty("catalina.useNaming");        if ((useNamingProperty != null)            && (useNamingProperty.equals("false"))) {            useNaming = false;        }        //如果当前context使用了JNDI,就为它添加监听器NamingContextListener        if (ok && isUseNaming()) {            if (getNamingContextListener() == null) {                NamingContextListener ncl = new NamingContextListener();                ncl.setName(getNamingContextName());                ncl.setExceptionOnFailedWrite(getJndiExceptionOnFailedWrite());                addLifecycleListener(ncl);                setNamingContextListener(ncl);            }        }        // Standard container startup        if (log.isDebugEnabled())            log.debug("Processing standard container startup");        // Binding thread        //绑定线程        ClassLoader oldCCL = bindThread();        try {            if (ok) {                // Start our subordinate components, if any                //开始我们的下一级别组件,如果有                Loader loader = getLoader();                if (loader instanceof Lifecycle) {                    ((Lifecycle) loader).start();//启动webAppLoader                }                // since the loader just started, the webapp classloader is now                // created.                setClassLoaderProperty("clearReferencesRmiTargets",                        getClearReferencesRmiTargets());                setClassLoaderProperty("clearReferencesStopThreads",                        getClearReferencesStopThreads());                setClassLoaderProperty("clearReferencesStopTimerThreads",                        getClearReferencesStopTimerThreads());                setClassLoaderProperty("clearReferencesHttpClientKeepAliveThread",                        getClearReferencesHttpClientKeepAliveThread());                // By calling unbindThread and bindThread in a row, we setup the                // current Thread CCL to be the webapp classloader                unbindThread(oldCCL);                oldCCL = bindThread();                // Initialize logger again. Other components might have used it                // too early, so it should be reset.                logger = null;                getLogger();                Realm realm = getRealmInternal();                if(null != realm) {                    if (realm instanceof Lifecycle) {                        ((Lifecycle) realm).start();//启动安全组件                    }                    // Place the CredentialHandler into the ServletContext so                    // applications can have access to it. Wrap it in a "safe"                    // handler so application's can't modify it.                    CredentialHandler safeHandler = new CredentialHandler() {                        @Override                        public boolean matches(String inputCredentials, String storedCredentials) {                            return getRealmInternal().getCredentialHandler().matches(inputCredentials, storedCredentials);                        }                        @Override                        public String mutate(String inputCredentials) {                            return getRealmInternal().getCredentialHandler().mutate(inputCredentials);                        }                    };                    context.setAttribute(Globals.CREDENTIAL_HANDLER, safeHandler);                }                // Notify our interested LifecycleListeners                //通知我们的相关的生命监听器                fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);//触发生命周期监听器                // Start our child containers, if not already started                for (Container child : findChildren()) {                    if (!child.getState().isAvailable()) {                        child.start();//启动context的子节点wrapper                    }                }                // Start the Valves in our pipeline (including the basic),                // if any                if (pipeline instanceof Lifecycle) {                    ((Lifecycle) pipeline).start();//启动context所维护的pipeline                }                // Acquire clustered manager                //创建会话管理器,如果有集群,由集群配置,否则由StandardManager()                Manager contextManager = null;                Manager manager = getManager();                if (manager == null) {                    if (log.isDebugEnabled()) {                        log.debug(sm.getString("standardContext.cluster.noManager",                                Boolean.valueOf((getCluster() != null)),                                Boolean.valueOf(distributable)));                    }                    if ( (getCluster() != null) && distributable) {                        try {                            contextManager = getCluster().createManager(getName());                        } catch (Exception ex) {                            log.error("standardContext.clusterFail", ex);                            ok = false;                        }                    } else {                        contextManager = new StandardManager();                    }                }                // Configure default manager if none was specified                //如果没有被指定配置默认的会话管理器                if (contextManager != null) {                    if (log.isDebugEnabled()) {                        log.debug(sm.getString("standardContext.manager",                                contextManager.getClass().getName()));                    }                    setManager(contextManager);                }                if (manager!=null && (getCluster() != null) && distributable) {                    //let the cluster know that there is a context that is distributable                    //and that it has its own manager                    getCluster().registerManager(manager);                }            }            if (!getConfigured()) {                log.error(sm.getString("standardContext.configurationFail"));                ok = false;            }            // We put the resources into the servlet context            //我们把资源(WebResourceRoot里面的资源)放到servletContext里面去            if (ok)                getServletContext().setAttribute                    (Globals.RESOURCES_ATTR, getResources());            if (ok ) {                if (getInstanceManager() == null) {                    javax.naming.Context context = null;                    if (isUseNaming() && getNamingContextListener() != null) {                        context = getNamingContextListener().getEnvContext();                    }                    Map<String, Map<String, String>> injectionMap = buildInjectionMap(                            getIgnoreAnnotations() ? new NamingResourcesImpl(): getNamingResources());                    setInstanceManager(new DefaultInstanceManager(context,                            injectionMap, this, this.getClass().getClassLoader()));//创建实例对象管理器,用于创建实例对象,如servlet,Filter                }                getServletContext().setAttribute(                        InstanceManager.class.getName(), getInstanceManager());                InstanceManagerBindings.bind(getLoader().getClassLoader(), getInstanceManager());            }            // Create context attributes that will be required            //将jar包扫描器放到ServletContext的属性里面去            if (ok) {                getServletContext().setAttribute(                        JarScanner.class.getName(), getJarScanner());            }            // Set up the context init params            //合并ServletContext参数和ApplicationParmeter的参数            mergeParameters();            // Call ServletContainerInitializers添加web应用的配置,如servlet,Filter            //调用这个方法以可编程的方式添加            for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry :                initializers.entrySet()) {                try {                    entry.getKey().onStartup(entry.getValue(),                            getServletContext());                } catch (ServletException e) {                    log.error(sm.getString("standardContext.sciFail"), e);                    ok = false;                    break;                }            }            // Configure and call application event listeners            //实例化应用监听器            if (ok) {                if (!listenerStart()) {                    log.error(sm.getString("standardContext.listenerFail"));                    ok = false;                }            }            // Check constraints for uncovered HTTP methods            // Needs to be after SCIs and listeners as they may programmatically            // change constraints            //检测未覆盖的http方法的安全约束            if (ok) {                checkConstraintsForUncoveredMethods(findConstraints());            }            try {                // Start manager                //启动会话管理器                Manager manager = getManager();                if (manager instanceof Lifecycle) {                    ((Lifecycle) manager).start();                }            } catch(Exception e) {                log.error(sm.getString("standardContext.managerFail"), e);                ok = false;            }            // Configure and call application filters            //配置并且调用应用过滤器            if (ok) {                if (!filterStart()) {                    log.error(sm.getString("standardContext.filterFail"));                    ok = false;                }            }            // Load and initialize all "load on startup" servlets            //实例化servlet            if (ok) {                if (!loadOnStartup(findChildren())){                    log.error(sm.getString("standardContext.servletFail"));                    ok = false;                }            }            // Start ContainerBackgroundProcessor thread            //开始后台的进程            super.threadStart();        } finally {            // Unbinding thread            unbindThread(oldCCL);        }        // Set available status depending upon startup success        if (ok) {            if (log.isDebugEnabled())                log.debug("Starting completed");        } else {            log.error(sm.getString("standardContext.startFailed", getName()));        }        startTime=System.currentTimeMillis();        // Send j2ee.state.running notification        //发布正在运行的JMX通知        if (ok && (this.getObjectName() != null)) {            Notification notification =                new Notification("j2ee.state.running", this.getObjectName(),                                 sequenceNumber.getAndIncrement());            broadcaster.sendNotification(notification);        }        // The WebResources implementation caches references to JAR files. On        // some platforms these references may lock the JAR files. Since web        // application start is likely to have read from lots of JARs, trigger        // a clean-up now.        //释放资源        getResources().gc();        // Reinitializing if something went wrong        if (!ok) {            setState(LifecycleState.FAILED);        } else {            setState(LifecycleState.STARTING);        }    }

看这一行代码,触发了生命周期事件,这个监听器是ContextConfig,相关操作在ContextConfig章节里面进行分析。
这里写图片描述
再看这一行代码,初始化了servlet
这里写图片描述
看load on startup这个方法:

public boolean loadOnStartup(Container children[]) {        // Collect "load on startup" servlets that need to be initialized        TreeMap<Integer, ArrayList<Wrapper>> map = new TreeMap<>();        for (int i = 0; i < children.length; i++) {            Wrapper wrapper = (Wrapper) children[i];            int loadOnStartup = wrapper.getLoadOnStartup();            if (loadOnStartup < 0)                continue;            Integer key = Integer.valueOf(loadOnStartup);            ArrayList<Wrapper> list = map.get(key);            if (list == null) {                list = new ArrayList<>();                map.put(key, list);            }            list.add(wrapper);        }        // Load the collected "load on startup" servlets        for (ArrayList<Wrapper> list : map.values()) {            for (Wrapper wrapper : list) {                try {                    wrapper.load();/*实例化servlet并对servlet进行初始化*/                } catch (ServletException e) {                    getLogger().error(sm.getString("standardContext.loadOnStartup.loadException",                          getName(), wrapper.getName()), StandardWrapper.getRootCause(e));                    // NOTE: load errors (including a servlet that throws                    // UnavailableException from the init() method) are NOT                    // fatal to application startup                    // unless failCtxIfServletStartFails="true" is specified                    if(getComputedFailCtxIfServletStartFails()) {                        return false;                    }                }            }        }        return true;    }

这里写图片描述
可以看到最终转向了StandardWrapper。
Tomcat8.5源码分析—ContextConfig

原创粉丝点击