zoukankan      html  css  js  c++  java
  • tomcat源码分析 MBeanFactory#createStandardContext过程

    这个方法主要是启动一个web项目,

    可以想象一下,所有跟web项目配置相关的信息,都会在这个方法里间接调用到,listener, servlet, filter等在web.xml配置的信息,还有一些通过注解配置的信息,tomcat都会扫描出来,并做初始化工作。

    1、生成StandardContext实例,并设置属性。

    // Create a new StandardContext instance
            StandardContext context = new StandardContext();
            path = getPathStr(path);
            context.setPath(path);
            context.setDocBase(docBase);
            context.setXmlValidation(xmlValidation);
            context.setXmlNamespaceAware(xmlNamespaceAware);
            context.setTldValidation(tldValidation);
            context.setTldNamespaceAware(tldNamespaceAware);

    2、生成ContextConfig实例。ContextConfig实现了LifecycleListener接口,该接口最重要的方法是

    public void lifecycleEvent(LifecycleEvent event);

    在ContextConfig实现这个方法,并注册到StandardContext上,对StandardContext实例触发的一些重要事件做出回应。

    ContextConfig contextConfig = new ContextConfig();
    context.addLifecycleListener(contextConfig);

    3、设置StandardContext的config属性,即根据哪个配置文件加载这个项目的。

       在我这个环境下是:file:/....../conf/Catalina/localhost/ROOT.xml

    4、以MBean的方式调用HostConfig的manageApp方法,参数即为StandardContext实例。

        这一步将StandardContext添加到Host上,

    host.addChild(context);

    5、在addChild过程中,将调用StandardContext的startInternal进行初始化工作。

    /**
         * Start this component and implement the requirements
         * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
         *
         * @exception LifecycleException if this component detects a fatal error
         *  that prevents this component from being used
         */
        @Override
        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
            if (namingResources != null) {
                namingResources.start();
            }
            
            // Add missing components as necessary
            if (webappResources == null) {   // (1) Required by Loader
                if (log.isDebugEnabled())
                    log.debug("Configuring default Resources");
                try {
                    if ((getDocBase() != null) && (getDocBase().endsWith(".war")) &&
                            (!(new File(getBasePath())).isDirectory()))
                        setResources(new WARDirContext());
                    else
                        setResources(new FileDirContext());
                } catch (IllegalArgumentException e) {
                    log.error("Error initializing resources: " + e.getMessage());
                    ok = false;
                }
            }
            if (ok) {
                if (!resourcesStart()) {
                    log.error( "Error in resourceStart()");
                    ok = false;
                }
            }
    
            if (getLoader() == null) {
                WebappLoader webappLoader = new WebappLoader(getParentClassLoader());
                webappLoader.setDelegate(getDelegate());
                setLoader(webappLoader);
            }
    
            // 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("Error in dependencyCheck", ioe);
                dependencyCheck = false;
            }
    
            if (!dependencyCheck) {
                // do not make application available if depency check fails
                ok = false;
            }
    
            // Reading the "catalina.useNaming" environment variable
            String useNamingProperty = System.getProperty("catalina.useNaming");
            if ((useNamingProperty != null)
                && (useNamingProperty.equals("false"))) {
                useNaming = false;
            }
    
            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
                    if ((loader != null) && (loader instanceof Lifecycle))
                        ((Lifecycle) loader).start();
    
                    // since the loader just started, the webapp classloader is now
                    // created.
                    // 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();
                    
                    if ((cluster != null) && (cluster instanceof Lifecycle))
                        ((Lifecycle) cluster).start();
                    Realm realm = getRealmInternal();
                    if ((realm != null) && (realm instanceof Lifecycle))
                        ((Lifecycle) realm).start();
                    if ((resources != null) && (resources instanceof Lifecycle))
                        ((Lifecycle) resources).start();
    
                    // 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();
                        }
                    }
    
                    // Start the Valves in our pipeline (including the basic),
                    // if any
                    if (pipeline instanceof Lifecycle) {
                        ((Lifecycle) pipeline).start();
                    }
                    
                    // Acquire clustered manager
                    Manager contextManager = null;
                    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);
                    }
                }
    
            } finally {
                // Unbinding thread
                unbindThread(oldCCL);
            }
    
            if (!getConfigured()) {
                log.error( "Error getConfigured");
                ok = false;
            }
    
            // We put the resources into the servlet context
            if (ok)
                getServletContext().setAttribute
                    (Globals.RESOURCES_ATTR, getResources());
    
            // Initialize associated mapper
            mapper.setContext(getPath(), welcomeFiles, resources);
    
            // Binding thread
            oldCCL = bindThread();
    
            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 NamingResources(): getNamingResources());
                    setInstanceManager(new DefaultInstanceManager(context,
                            injectionMap, this, this.getClass().getClassLoader()));
                    getServletContext().setAttribute(
                            InstanceManager.class.getName(), getInstanceManager());
                }
            }
    
            try {
                // Create context attributes that will be required
                if (ok) {
                    getServletContext().setAttribute(
                            JarScanner.class.getName(), getJarScanner());
                }
    
                // Set up the context init params
                mergeParameters();
    
                // Call ServletContainerInitializers
                for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry :
                    initializers.entrySet()) {
                    try {
                        entry.getKey().onStartup(entry.getValue(),
                                getServletContext());
                    } catch (ServletException e) {
                        // TODO: Log error
                        ok = false;
                        break;
                    }
                }
    
                // Configure and call application event listeners
                if (ok) {
                    if (!listenerStart()) {
                        log.error( "Error listenerStart");
                        ok = false;
                    }
                }
                
                try {
                    // Start manager
                    if ((manager != null) && (manager instanceof Lifecycle)) {
                        ((Lifecycle) getManager()).start();
                    }
        
                    // Start ContainerBackgroundProcessor thread
                    super.threadStart();
                } catch(Exception e) {
                    log.error("Error manager.start()", e);
                    ok = false;
                }
    
                // Configure and call application filters
                if (ok) {
                    if (!filterStart()) {
                        log.error("Error filterStart");
                        ok = false;
                    }
                }
                
                // Load and initialize all "load on startup" servlets
                if (ok) {
                    loadOnStartup(findChildren());
                }
                
            } 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 
            if (ok && (this.getObjectName() != null)) {
                Notification notification = 
                    new Notification("j2ee.state.running", this.getObjectName(),
                                     sequenceNumber.getAndIncrement());
                broadcaster.sendNotification(notification);
            }
    
            // Close all JARs right away to avoid always opening a peak number 
            // of files on startup
            if (getLoader() instanceof WebappLoader) {
                ((WebappLoader) getLoader()).closeJARs(true);
            }
    
            // Reinitializing if something went wrong
            if (!ok) {
                setState(LifecycleState.FAILED);
            } else {
                setState(LifecycleState.STARTING);
            }
        }

    这一步做了太多工作,接下来我们再做一些分析工作。

  • 相关阅读:
    App调试的几个命令实践【转】
    解决sdk更新时候报错 http://dl-ssl.google.com/android上不去,链接拒绝
    fastjson序列化排序问题
    Java中的四种引用
    equal&==&hashcode
    ThreadPool线程池的关注点
    JVM的本地方法栈
    JVM的堆分配
    JVM的类装载子系统
    JVM的数据类型
  • 原文地址:https://www.cnblogs.com/knockon/p/3337661.html
Copyright © 2011-2022 走看看