关于java:tomcat源码分析

50次阅读

共计 20202 个字符,预计需要花费 51 分钟才能阅读完成。

tomcat 整体架构

Server:代表整个服务,也能够了解为 tomcat。
service: 代表一个服务,它将若干个 connector 和 contain 连接起来。
connector:连接器,解决用户的 web 申请,反对三种协定:
AJP
HTTP
HTTPS

Container:容器,能够看做 servelet 容器。
engine:servelet 引擎,一个 container 只能有一个 engine,engine 也能够看做是 container 自身。
host:虚拟主机,比方 www.baidu.com,localhost,一个 engine 能够有多个 host。
context:代表一个利用,比方订单服务 order,url 就为 localhost/order, 用户服务 user,url 就为 localhost/user。一个 host 能够有多个 context
Wrapper:servelet,比方订单信息,url 就为 localhost/order/detail/1,一个 context 能够有多个 wrapper。

从配置文件 server.xml 更能感触分层构造:

tomcat 初始化流程

启动流程:
BootStrap.main->
BootStrap.load->Catalina.load->Server.init->Service.init->engine.init->connector.init->

BootStrap.start->Server.start->service-start->engine.start->host.start(被 engine 异步启动)->context.start(被 host 异步启动)->connector.start

能够看到,次要分两步 BootStrap 的 load 和 start 办法,这两个办法里都是逐级调用下一级的 init 或 start 办法。

从咱们启动 tomcat 的命令:./start.sh 动手:

#!/bin/sh

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# -----------------------------------------------------------------------------
# Start Script for the CATALINA Server
# -----------------------------------------------------------------------------

# Better OS/400 detection: see Bugzilla 31132
os400=false
case "`uname`" in
OS400*) os400=true;;
esac

# resolve links - $0 may be a softlink
PRG="$0"

while [-h "$PRG"] ; do
  ls=`ls -ld "$PRG"`
  link=`expr "$ls" : '.*-> \(.*\)$'`
  if expr "$link" : '/.*' > /dev/null; then
    PRG="$link"
  else
    PRG=`dirname "$PRG"`/"$link"
  fi
done

PRGDIR=`dirname "$PRG"`
#通过 catalina.sh 来执行
EXECUTABLE=catalina.sh

# Check that target executable exists
if $os400; then
  # -x will Only work on the os400 if the files are:
  # 1. owned by the user
  # 2. owned by the PRIMARY group of the user
  # this will not work if the user belongs in secondary groups
  eval
else
  if [! -x "$PRGDIR"/"$EXECUTABLE"]; then
    echo "Cannot find $PRGDIR/$EXECUTABLE"
    echo "The file is absent or does not have execute permission"
    echo "This file is needed to run this program"
    exit 1
  fi
fi

exec "$PRGDIR"/"$EXECUTABLE" start "[email protected]"

看看 catalina.sh 文件,代码太长,咱们间接看启动局部:

 if ["$1" = "-security"] ; then
    if [$have_tty -eq 1]; then
      echo "Using Security Manager"
    fi
    shift
    eval $_NOHUP "\"$_RUNJAVA\"""\"$CATALINA_LOGGING_CONFIG\""$LOGGING_MANAGER"$JAVA_OPTS""$CATALINA_OPTS" \
      -D$ENDORSED_PROP="\"$JAVA_ENDORSED_DIRS\"" \
      -classpath "\"$CLASSPATH\"" \
      -Djava.security.manager \
      -Djava.security.policy=="\"$CATALINA_BASE/conf/catalina.policy\"" \
      -Dcatalina.base="\"$CATALINA_BASE\"" \
      -Dcatalina.home="\"$CATALINA_HOME\"" \
      -Djava.io.tmpdir="\"$CATALINA_TMPDIR\"" \
      # 启动 Bootstrap 类,并将 start 作为参数传进去
      org.apache.catalina.startup.Bootstrap "[email protected]" start \
      >> "$CATALINA_OUT" 2>&1 "&"

当初进入 java 代码,BootStrap 类:

 public static void main(String args[]) {synchronized (daemonLock) {if (daemon == null) {// Don't set daemon until init() has completed
                Bootstrap bootstrap = new Bootstrap();
                try {
                    // 初始化 Bootstrap
                    bootstrap.init();} catch (Throwable t) {handleThrowable(t);
                    t.printStackTrace();
                    return;
                }
                // 初始化实现后再赋值给 daemon
                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);
            }
        }

        try {
            String command = "start";
            if (args.length > 0) {command = args[args.length - 1];
            }


            if (command.equals("startd")) {args[args.length - 1] = "start";

                daemon.load(args);
                daemon.start();} else if (command.equals("stopd")) {args[args.length - 1] = "stop";
                daemon.stop();}
            // 启动时走这里
            else if (command.equals("start")) {daemon.setAwait(true);
                // load 并且 start
                daemon.load(args);
                daemon.start();
                if (null == daemon.getServer()) {System.exit(1);
                }
            } else if (command.equals("stop")) {daemon.stopServer(args);
            } else if (command.equals("configtest")) {daemon.load(args);
                if (null == daemon.getServer()) {System.exit(1);
                }
                System.exit(0);
            } else {log.warn("Bootstrap: command \"" + command + "\" does not exist.");
            }
        } catch (Throwable t) {
            // Unwrap the Exception for clearer error reporting
            if (t instanceof InvocationTargetException &&
                    t.getCause() != null) {t = t.getCause();
            }
            handleThrowable(t);
            t.printStackTrace();
            System.exit(1);
        }
    }

首先初始化 Bootstrap 类,而后依据传入的参数执行不同操作,启动就是执行 load 和 start 办法,先看 init 办法做了什么:

 public void init() throws Exception {


        // 初始化类加载器
        initClassLoaders();

        Thread.currentThread().setContextClassLoader(catalinaLoader);

        SecurityClassLoad.securityClassLoad(catalinaLoader);

        // Load our startup class and call its process() method
        if (log.isDebugEnabled()) {log.debug("Loading startup class");
        }
        Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
        Object startupInstance = startupClass.getConstructor().newInstance();

        // Set the shared extensions class loader
        if (log.isDebugEnabled()) {log.debug("Setting startup class properties");
        }
        String methodName = "setParentClassLoader";
        Class<?> paramTypes[] = new Class[1];
        // 指定
        paramTypes[0] = Class.forName("java.lang.ClassLoader");
        Object paramValues[] = new Object[1];
        paramValues[0] = sharedLoader;
        Method method =
            startupInstance.getClass().getMethod(methodName, paramTypes);
        // Catalina 的父类加载器设为 sharedLoader
        method.invoke(startupInstance, paramValues);

        catalinaDaemon = startupInstance;  //Catalina 实例
    }

initClassLoaders():

     
    private void initClassLoaders() {
        try {
            // 初始化 common 类加载器
            commonLoader = createClassLoader("common", null);
            if (commonLoader == null) {
                // no config file, default to this loader - we might be in a 'single' env.
                commonLoader = this.getClass().getClassLoader();
            }
            // 父类加载器为 commonLoader
            catalinaLoader = createClassLoader("server", commonLoader);
            sharedLoader = createClassLoader("shared", commonLoader);
        } catch (Throwable t) {handleThrowable(t);
            log.error("Class loader creation threw exception", t);
            System.exit(1);
        }
    }


   private ClassLoader createClassLoader(String name, ClassLoader parent)
        throws Exception {

        //  catalinaLoader 和 sharedLoader 的加门路为空,所以应用父类加载器
        String value = CatalinaProperties.getProperty(name + ".loader");
        if ((value == null) || (value.equals(""))) {return parent;}

        value = replace(value);

        List<Repository> repositories = new ArrayList<>();

        String[] repositoryPaths = getPaths(value);

        for (String repository : repositoryPaths) {
            // Check for a JAR URL repository
            try {@SuppressWarnings("unused")
                URL url = new URL(repository);
                repositories.add(new Repository(repository, RepositoryType.URL));
                continue;
            } catch (MalformedURLException e) {// Ignore}

            // 遍历指定目录下的 jar 包
            // Local repository
            if (repository.endsWith("*.jar")) {
                repository = repository.substring
                    (0, repository.length() - "*.jar".length());
                repositories.add(new Repository(repository, RepositoryType.GLOB));
            } else if (repository.endsWith(".jar")) {repositories.add(new Repository(repository, RepositoryType.JAR));
            } else {repositories.add(new Repository(repository, RepositoryType.DIR));
            }
        }

        return ClassLoaderFactory.createClassLoader(repositories, parent);
    }

initClassLoaders 办法初始化了三个类加载器:commonLoader,catalinaLoader,sharedLoader,并将 catalinaLoader,sharedLoader 的父类加载器指定为 commonLoader,初始化类加载器后又实例化了 catalina 实例,init 办法完结,再看 load 办法:

    /**
     * Load daemon.
     */
    private void load(String[] arguments) throws Exception {// Call the load() method
        String methodName = "load";
        Object param[];
        Class<?> paramTypes[];
        if (arguments==null || arguments.length==0) {
            paramTypes = null;
            param = null;
        } else {paramTypes = new Class[1];
            paramTypes[0] = arguments.getClass();
            param = new Object[1];
            param[0] = arguments;
        }
        Method method =
            catalinaDaemon.getClass().getMethod(methodName, paramTypes);
        if (log.isDebugEnabled()) {log.debug("Calling startup class" + method);
        }
        // 调用了 catalina 的 load 办法
        method.invoke(catalinaDaemon, param);
    }

其实就是调用了 Catalina 的 load 办法:

 public void load() {if (loaded) {return;}
        loaded = true;

        long t1 = System.nanoTime();

        initDirs();

        // Before digester - it may be needed
        initNaming();

        // Create and execute our Digester
        //xml 文件解析器,比方解析 server.xml
        Digester digester = createStartDigester();

        InputSource inputSource = null;
        InputStream inputStream = null;
        File file = null;
        try {
            try {file = configFile();
                inputStream = new FileInputStream(file);
                inputSource = new InputSource(file.toURI().toURL().toString());
            } catch (Exception e) {if (log.isDebugEnabled()) {log.debug(sm.getString("catalina.configFail", file), e);
                }
            }
            if (inputStream == null) {
                try {inputStream = getClass().getClassLoader()
                        .getResourceAsStream(getConfigFile());
                    inputSource = new InputSource
                        (getClass().getClassLoader()
                         .getResource(getConfigFile()).toString());
                } catch (Exception e) {if (log.isDebugEnabled()) {
                        log.debug(sm.getString("catalina.configFail",
                                getConfigFile()), e);
                    }
                }
            }

            // This should be included in catalina.jar
            // Alternative: don't bother with xml, just create it manually.
            if (inputStream == null) {
                try {inputStream = getClass().getClassLoader()
                            .getResourceAsStream("server-embed.xml");
                    inputSource = new InputSource
                    (getClass().getClassLoader()
                            .getResource("server-embed.xml").toString());
                } catch (Exception e) {if (log.isDebugEnabled()) {
                        log.debug(sm.getString("catalina.configFail",
                                "server-embed.xml"), e);
                    }
                }
            }


            if (inputStream == null || inputSource == null) {if  (file == null) {
                    log.warn(sm.getString("catalina.configFail",
                            getConfigFile() + "] or [server-embed.xml]"));
                } else {
                    log.warn(sm.getString("catalina.configFail",
                            file.getAbsolutePath()));
                    if (file.exists() && !file.canRead()) {log.warn("Permissions incorrect, read permission is not allowed on the file.");
                    }
                }
                return;
            }

            try {inputSource.setByteStream(inputStream);
                digester.push(this);
                digester.parse(inputSource);
            } catch (SAXParseException spe) {log.warn("Catalina.start using" + getConfigFile() + ":" +
                        spe.getMessage());
                return;
            } catch (Exception e) {log.warn("Catalina.start using" + getConfigFile() + ":" , e);
                return;
            }
        } finally {if (inputStream != null) {
                try {inputStream.close();
                } catch (IOException e) {// Ignore}
            }
        }

        getServer().setCatalina(this);
        getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
        getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());

        // Stream redirection
        initStreams();

        // Start the new server
        try {
            // 重点看 init 办法
            getServer().init();
        } catch (LifecycleException e) {if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {throw new java.lang.Error(e);
            } else {log.error("Catalina.start", e);
            }
        }

        long t2 = System.nanoTime();
        if(log.isInfoEnabled()) {log.info("Initialization processed in" + ((t2 - t1) / 1000000) + "ms");
        }
    }

getServer().init() 会调用 LifeCycleBase 的 init 办法,LifeCycle 是一个治理 tomcat 生命周期的接口,LifeCycleBase 是它的实现类:

    @Override
    public final synchronized void init() throws LifecycleException {if (!state.equals(LifecycleState.NEW)) {invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }

        try {setStateInternal(LifecycleState.INITIALIZING, null, false);
            // 进入这里
            initInternal();
            setStateInternal(LifecycleState.INITIALIZED, null, false);
        } catch (Throwable t) {handleSubClassException(t, "lifecycleBase.initFail", toString());
        }
    }

initInternal() 是个形象办法,由 StandServer 实现:

    @Override
    protected void initInternal() throws LifecycleException {super.initInternal();

        // Register global String cache
        // Note although the cache is global, if there are multiple Servers
        // present in the JVM (may happen when embedding) then the same cache
        // will be registered under multiple names
        onameStringCache = register(new StringCache(), "type=StringCache");

        // Register the MBeanFactory
        MBeanFactory factory = new MBeanFactory();
        factory.setContainer(this);
        onameMBeanFactory = register(factory, "type=MBeanFactory");

        // Register the naming resources
        globalNamingResources.init();

        // Populate the extension validator with JARs from common and shared
        // class loaders
        if (getCatalina() != null) {ClassLoader cl = getCatalina().getParentClassLoader();
            // Walk the class loader hierarchy. Stop at the system class loader.
            // This will add the shared (if present) and common class loaders
            while (cl != null && cl != ClassLoader.getSystemClassLoader()) {if (cl instanceof URLClassLoader) {URL[] urls = ((URLClassLoader) cl).getURLs();
                    for (URL url : urls) {if (url.getProtocol().equals("file")) {
                            try {File f = new File (url.toURI());
                                if (f.isFile() &&
                                        f.getName().endsWith(".jar")) {ExtensionValidator.addSystemResource(f);
                                }
                            } catch (URISyntaxException | IOException e) {// Ignore}
                        }
                    }
                }
                cl = cl.getParent();}
        }
        // Initialize our defined Services
        for (Service service : services) {
            // 进入这里
            service.init();}
    }

service 是 StandService,但它的 init 是父类 LifeCycleBase 的办法,又一次运行了这个办法:


    @Override
    public final synchronized void init() throws LifecycleException {if (!state.equals(LifecycleState.NEW)) {invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }

        try {setStateInternal(LifecycleState.INITIALIZING, null, false);
            // 进入这里,这里由 StandService 实现
            initInternal();
            setStateInternal(LifecycleState.INITIALIZED, null, false);
        } catch (Throwable t) {handleSubClassException(t, "lifecycleBase.initFail", toString());
        }
    }
       @Override
    protected void initInternal() throws LifecycleException {super.initInternal();

        if (engine != null) {
            // 初始化 engine
            engine.init();}

        // Initialize any Executors
        for (Executor executor : findExecutors()) {if (executor instanceof JmxEnabled) {((JmxEnabled) executor).setDomain(getDomain());
            }
            // 初始化 executor
            executor.init();}

        // Initialize mapper listener
        // 初始化 mapperListener
        mapperListener.init(); 

        // Initialize our defined Connectors
        synchronized (connectorsLock) {for (Connector connector : connectors) {
                try {
                    // 初始化 connector
                    connector.init();} catch (Exception e) {
                    String message = sm.getString("standardService.connector.initFailed", connector);
                    log.error(message, e);

                    if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {throw new LifecycleException(message);
                    }
                }
            }
        }
    }

又一次调用了 LifeCycleBase 的 init 办法:

    @Override
    public final synchronized void init() throws LifecycleException {if (!state.equals(LifecycleState.NEW)) {invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }

        try {setStateInternal(LifecycleState.INITIALIZING, null, false);
            // 进入这里,这次由 Connect 实现
            initInternal();
            setStateInternal(LifecycleState.INITIALIZED, null, false);
        } catch (Throwable t) {handleSubClassException(t, "lifecycleBase.initFail", toString());
        }
    }
    @Override
    protected void initInternal() throws LifecycleException {super.initInternal();

        // Initialize adapter
        adapter = new CoyoteAdapter(this);
        protocolHandler.setAdapter(adapter);

        // Make sure parseBodyMethodsSet has a default
        if (null == parseBodyMethodsSet) {setParseBodyMethods(getParseBodyMethods());
        }

        if (protocolHandler.isAprRequired() && !AprLifecycleListener.isInstanceCreated()) {
            throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprListener",
                    getProtocolHandlerClassName()));
        }
        if (protocolHandler.isAprRequired() && !AprLifecycleListener.isAprAvailable()) {
            throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoAprLibrary",
                    getProtocolHandlerClassName()));
        }
        if (AprLifecycleListener.isAprAvailable() && AprLifecycleListener.getUseOpenSSL() &&
                protocolHandler instanceof AbstractHttp11JsseProtocol) {
            AbstractHttp11JsseProtocol<?> jsseProtocolHandler =
                    (AbstractHttp11JsseProtocol<?>) protocolHandler;
            if (jsseProtocolHandler.isSSLEnabled() &&
                    jsseProtocolHandler.getSslImplementationName() == null) {
                // OpenSSL is compatible with the JSSE configuration, so use it if APR is available
                jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName());
            }
        }

        try {
            // 初始化 ProtocolHandler
            protocolHandler.init();} catch (Exception e) {
            throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
        }
    }

protocolHandler.init() 由 AbstractProtocol 实现:

    @Override
    public void init() throws Exception {if (getLog().isInfoEnabled()) {getLog().info(sm.getString("abstractProtocolHandler.init", getName()));
            logPortOffset();}

        if (oname == null) {
            // Component not pre-registered so register it
            oname = createObjectName();
            if (oname != null) {Registry.getRegistry(null, null).registerComponent(this, oname, null);
            }
        }

        if (this.domain != null) {ObjectName rgOname = new ObjectName(domain + ":type=GlobalRequestProcessor,name=" + getName());
            this.rgOname = rgOname;
            Registry.getRegistry(null, null).registerComponent(getHandler().getGlobal(), rgOname, null);
        }

        String endpointName = getName();
        endpoint.setName(endpointName.substring(1, endpointName.length()-1));
        endpoint.setDomain(domain);
 
        // 初始化 endPoint
        endpoint.init();}

endpoint.init() 由 AbstractEndPoint 实现:

    public void init() throws Exception {if (bindOnInit) {
            // 重点在这里
            bindWithCleanup();
            bindState = BindState.BOUND_ON_INIT;
        }
        if (this.domain != null) {// Register endpoint (as ThreadPool - historical name)
            oname = new ObjectName(domain + ":type=ThreadPool,name=\"" + getName() + "\"");
            Registry.getRegistry(null, null).registerComponent(this, oname, null);

            ObjectName socketPropertiesOname = new ObjectName(domain +
                    ":type=SocketProperties,name=\"" + getName() + "\"");
            socketProperties.setObjectName(socketPropertiesOname);
            Registry.getRegistry(null, null).registerComponent(socketProperties, socketPropertiesOname, null);

            for (SSLHostConfig sslHostConfig : findSslHostConfigs()) {registerJmx(sslHostConfig);
            }
        }
    }



    private void bindWithCleanup() throws Exception {
        try {bind();
        } catch (Throwable t) {
            // Ensure open sockets etc. are cleaned up if something goes
            // wrong during bind
            ExceptionUtils.handleThrowable(t);
            unbind();
            throw t;
        }
    }

进入 NioEndPoint:

      /**
     * Initialize the endpoint.
     */
    @Override
    public void bind() throws Exception {
        // 初始化 ServerSocket
        initServerSocket();

        setStopLatch(new CountDownLatch(1));

        // Initialize SSL if needed
        initialiseSsl();}








    // Separated out to make it easier for folks that extend NioEndpoint to
    // implement custom [server]sockets
    protected void initServerSocket() throws Exception {if (getUseInheritedChannel()) {
            // Retrieve the channel provided by the OS
            Channel ic = System.inheritedChannel();
            if (ic instanceof ServerSocketChannel) {serverSock = (ServerSocketChannel) ic;
            }
            if (serverSock == null) {throw new IllegalArgumentException(sm.getString("endpoint.init.bind.inherited"));
            }
        } else {serverSock = ServerSocketChannel.open();
            socketProperties.setProperties(serverSock.socket());
            InetSocketAddress addr = new InetSocketAddress(getAddress(), getPortWithOffset());
            serverSock.socket().bind(addr,getAcceptCount());
        }
        serverSock.configureBlocking(true); //mimic APR behavior
    }

BootStrap 的 load 办法实现,就是初始化了一些组件。
再来看 start 办法:

    /**
     * Start the Catalina daemon.
     * @throws Exception Fatal start error
     */
    public void start() throws Exception {if (catalinaDaemon == null) {init();
        }

        Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);
        // 调用 Catalina 的 start 办法
        method.invoke(catalinaDaemon, (Object [])null);
    }


 /**
     * Start a new server instance.
     */
    public void start() {if (getServer() == null) {load();
        }

        if (getServer() == null) {log.fatal("Cannot start server. Server instance is not configured.");
            return;
        }

        long t1 = System.nanoTime();

        // Start the new server
        try {
            // start
            getServer().start();
        } catch (LifecycleException e) {log.fatal(sm.getString("catalina.serverStartFail"), e);
            try {getServer().destroy();} catch (LifecycleException e1) {log.debug("destroy() failed for failed Server", e1);
            }
            return;
        }

        long t2 = System.nanoTime();
        if(log.isInfoEnabled()) {log.info("Server startup in" + ((t2 - t1) / 1000000) + "ms");
        }

        // Register shutdown hook
        if (useShutdownHook) {if (shutdownHook == null) {shutdownHook = new CatalinaShutdownHook();
            }
            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()
            LogManager logManager = LogManager.getLogManager();
            if (logManager instanceof ClassLoaderLogManager) {((ClassLoaderLogManager) logManager).setUseShutdownHook(false);
            }
        }

        if (await) {await();
            stop();}
    }

getServer().start() 调用 LifecycleBase 的 start 办法:

    /**
     * {@inheritDoc}
     */
    @Override
    public final synchronized void start() throws LifecycleException {if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
                LifecycleState.STARTED.equals(state)) {if (log.isDebugEnabled()) {Exception e = new LifecycleException();
                log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
            } else if (log.isInfoEnabled()) {log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
            }

            return;
        }
       // start 办法时,state 为 INITIALIZED
        if (state.equals(LifecycleState.NEW)) {init();
        } else if (state.equals(LifecycleState.FAILED)) {stop();
        } else if (!state.equals(LifecycleState.INITIALIZED) &&
                !state.equals(LifecycleState.STOPPED)) {invalidTransition(Lifecycle.BEFORE_START_EVENT);
        }

        try {setStateInternal(LifecycleState.STARTING_PREP, null, false);
            // 进入这里,调用的是 StandServer 的 startInternal()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();} else if (!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());
        }
    }


 @Override
    protected void startInternal() throws LifecycleException {fireLifecycleEvent(CONFIGURE_START_EVENT, null);
        setState(LifecycleState.STARTING);

        globalNamingResources.start();

        // Start our defined Services
        synchronized (servicesLock) {for (Service service : services) {
                // standService
                service.start();}
        }
    }

前面和 load 办法一样,都是调用了父类 LifecycleBase 的模板办法实现各个组件的 start。

正文完
 0