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 31132os400=falsecase "`uname`" inOS400*) os400=true;;esac# resolve links - $0 may be a softlinkPRG="$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"  fidonePRGDIR=`dirname "$PRG"`#通过catalina.sh来执行EXECUTABLE=catalina.sh# Check that target executable existsif $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  evalelse  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  fifiexec "$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。