tomcat启动流程

tomcat 启动

启动流程

- Bootstrap.main()
    - Bootstrap bootstrap = new Bootstrap(); 实例化Bootstrap实例
    - bootstrap.init(); 1.设置catalinaHome和catalinaBase 2.初始化类加载器,实例化**ClassLoaders
        - setCatalinaHome(); 设置Catalina path,System.getProperty("catalina.home"),值为tomcat根目录
        - setCatalinaBase(); 值为D:\workspace-e3\.metadata\.plugins\org.eclipse.wst.server.core\tmp2
        - initClassLoaders(); 实例化**ClassLoaders,创建URLClassLoader
            - 初始化classloader,第二个参数为父classLoader commonLoader = createClassLoader("common", null); catalinaLoader = createClassLoader("server", commonLoader); sharedLoader = createClassLoader("shared", commonLoader); 最终执行结果是,创建了commonLoader,catalinaLoader 和 sharedLoader,其中 catalinaLoader 和 sharedLoader 默认均使用 父classLoader: 即 commonLoader
                - bootstrap.createClassLoader()
                    - 读取配置文件中配置的仓库路径(需要加载的jar包的路径) CatalinaProperties.getProperty(name + ".loader");
                        - CatalinaProperties类中静态块中 static {loadProperties();} 后续从properties中取
                            - loadProperties()方法, 读取catalina.base\\conf\\catalina.properties配置文件到prop属性中 D:\workspace-e3\.metadata\.plugins\org.eclipse.wst.server.core\tmp2\conf\catalina.properties
                    - bootstrap.replace()将${catalina.home}等替换成具体的路径
                    - 根据逗号截取出每个资源路径
                    - URL url = new URL(repository); 先判断是不是网络资源,即先尝试使用URL加载,若它是网络资源则能加载成功, 否则捕获异常接着下面使用本地加载
                    - 本地加载.根据路径结尾以*.jar,.jar或路径,创建不同类型的repository对象
                        - RepositoryType枚举类分类
                            - DIR,// 表示整个目录下的资源,包括所有Class,Jar包以及其他类型资源
                            - GLOB,// 表示整个目录下所有的Jar包资源,仅仅是.jar后缀的资源
                            - JAR,// 表示单个Jar包资源
                            - URL// 表示从URL上获取的Jar包资源
                    - 根据以上的repository列表创建classLoader. ClassLoaderFactory.createClassLoader(repositories, parent)
                        - 遍历repositories,判断repositoryType.目的是将每种资源转换为new URL(),并添加到URL[]数组中 
                        0.若是RepositoryType.URL类型的资源,直接new一个URL实例即可 
                        1.若是DIR类型,则根据路径创建java.net.URL对象; 
                        2.若是GLOB(这里是E:\Java\apache-tomcat-7.0.82-01\lib),则遍历该目录下的jar包,创建文件,每个jar文件对应一个URL对象;
                        - 最后根据以上所有的url,创建URLClassLoader并返回.该类构造器接收一个URL[]数组类型 return new URLClassLoader(array)
        - Thread.currentThread().setContextClassLoader(catalinaLoader); 为当前线程设置classLoader为catalinaLoader
        - 若启用了安全管理,则会在这里加载一些所需的包(默认不启用) SecurityClassLoad.securityClassLoad(catalinaLoader);
        - 使用catalinaLoader加载catalina类 Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina"); Object startupInstance = startupClass.newInstance();
        - 设置catalina对象的parentClassLoader属性为sharedLoader, 由于前面sharedLoader默认使用的是父加载器commonLoader, 所以此处相当于设置为commonLoader org.apache.catalina.startup.Catalina.setParentClassLoader(sharedLoader);
        - bootstrap对象 保存catalina的引用 catalinaDaemon = startupInstance;
    - 处理"start"命令
        - 1.setAwait(true) 设置catalina.await=true
        - 2.daemon.load(args); 加载配置资源,通过反射调用catalina.load()方法 (1)创建digester实例,digester解析conf/server.xml文件 (2)调用Server.init()级联初始化各个组件
            - Catalina中 initDirs() 设置catalina.base和catalina.home和user.dir的property属性, 检查java.io.tmpdir属性是否存在
            - initNaming() 设置java.naming.factory.url.pkgs和java.naming.factory.initia这两个System.setProperty
            - 创建并执行digester,使用digester解析server.xml Digester digester = createStartDigester(); Digester类按照预定的规则解析server.xml,将元素转化为对象, 包括构造对象,set属性到对象字段,同时维护相互关联关系
                - new Digester() 创建digester对象
                - digester.addObjectCreate() 1)添加对象创建规则ObjectCreateRule 2)SetPropertiesRule 3)SetNextRule 添加StandardServer等各级容器的关系和处理规则
                - 创建Server实例,默认实现类是StandardServer, 可以通过server节点的className属性指定自己的实现,一般不需要
                - 设置Server属性
                - 调用setServer()将Server设置到Catalina对象中.可在本Catalina类中搜索setServer()方法
                - 创建JNDI实例对象,GlobalNamingResources,并设置其属性.并调用standServer.setGlobalNamingResources()方法装配到server中
                - 为Server添加生命周期监听
                - 创建service实例,创建完成后,通过addService()添加到server中
                - 为server添加生命周期监听器.默认未指定监听器,347行的null
                - 为service添加Executor
                - 为service添加Connector
                - 设置属性时,将executor属性排除在外.因为Connector创建时,即ConnectorCreateRule类中, 会判断当前是否指定了executor属性.若是,则从Service中查找该名称的executor并设置到Connector中.
                - 为Connector添加 生命周期监听器.默认未指定
                - 添加子元素解析规则.这部分指定了Servlet容器相关的各级嵌套子节点的解析规则. 且每类嵌套子节点的解析封装为一个RuleSet类(跟进去看).包括GlobalNamingResources,Engine,Context,Cluster的解析
            - 使用sax读取server.xml file = configFile();
            - digester.parse(inputSource); 使用digester解析读取的xml,在此过程中会初始化各个组件实例及其依赖关系. 最后会把server.xml文件中的内容解析到StandardServer中 (创建standServer对象并维护对象间关系)
                - configure();
                - getXMLReader().parse(input);
                    - ......
                        - 经过java里SAXPaser解析InputSource后,调用Digester.startElement()
                            - 遍历rules rule.begin(namespaceURI, name, list); 分别创建StandardServer实例
                                - new StandardServer()构造器
                                    - new NamingResources()
                                    - new NamingContextListener() addLifecycleListener(namingContextListener);
                                - setPropertiesRule()
                            - standardService.addConnector()
                            - standardServer.addService() 向server中添加一个新的service. digester在xml解析时会注入这个关系
                            - digester解析会做很多初始化操作,以后细化...
                            - Connector con = new Connector(attributes.getValue("protocol")); 创建Connector,会有多个Connector,和xml中配置的数量有关
                                - Connector构造器
                                    - setProtocol(protocol);
                                        - 根据xml配置的协议类型,此处是Http11Protocol setProtocolHandlerClassName ("org.apache.coyote.http11.Http11Protocol");
                                    - 实例化Http11Protocol
                                        - Http11Protocol构造器
                                            - endpoint = new JIoEndpoint();
            - getServer().init(); 调用Server的init()方法,初始化各个组件. 它会调用各个service子容器的init()方法, 从而级联完成组件初始化 在调用init()时第3步,调用子类StandardService.initInternal(); 各个组件有个共同的父类: LifecycleBase,用于管理组件的生命周期和状态变化。 在走Server.init()前,先走父类LifecycleBase.init(),事件驱动当前组件状态的变化. 从StandardServer到StandardWrapper,都会调用initInternal(), 并伴随调用共有父类LifecycleBase.init()
                - init()方法在父类LifecycleBase中, 调用父类LifecycleBase.init()
                    - super.initInternal(); 即父类LifecycleBase.initInternal()
                        - 1.先判断状态是否为LifecycleState.NEW(默认是)  
                          2.LifecycleBase.setStateInternal(LifecycleState.INITIALIZING, null, false); 变更生命周期状态为LifecycleState.INITIALIZING 调用各个事件监听中的 初始化方法
                        - 3.initInternal();这个方法一般被子类覆盖,执行子类自己的逻辑 此处为StandServer.initInternal()
                            - StandServer.initInternal()中 super.initInternal(); 调用父类LifecycleMBeanBase.initInternal()
                                - LifecycleMBeanBase.initInternal()中 将容器托管到JMX,便于运维管理
                            - 遍历services调用service.init() services[i].init();
                                - StandardService.init()中 init()方法在父类LifecycleBase中, 调用父类LifecycleBase.init()
                                    - LifecycleBase.init()中 setStateInternal(LifecycleState.INITIALIZING, null, false); 变更生命周期状态为LifecycleState.INITIALIZING(通过事件变更)
                                    - initInternal();// 进入子类的initInternal()方法, 即调用StandardService.initInternal()
                                        - StandardService.initInternal()中 container.init(); 此处container即为StandardEngine.init()  StandardEngine的子容器standardContext及其子容器没有init初始化逻辑
                                            - StandardEngine.init()中,略去LifecycleBase中生命周期变更的重复逻辑 StandardEngine.initInternal()中 getRealm(); 创建realm
                                            - super.initInternal(); 即为ContainerBase.initInternal() Engine,Host,Context,Wrapper容器都拥有共同父类ContainerBase
                                                - ContainerBase.initInternal()中 startStopExecutor = new ThreadPoolExecutor() 初始化startStopExecutor,用于管理启动和关闭的线程
                                                - super.init()即LifecycleMBeanBase.initInternal()
                                                    - ......略去各个StandardHost.init()
                                                        - ...
                                                            - lifecycleBase.init()
                                                                - LifecycleBase.setStateInternal(LifecycleState.INITIALIZED, null, false);初始化完成 StandardContext父类LifecycleBase变更生命周期状态,调用各个事件监听中的 initializing
                                                                - initInternal();// 进入子类StandardContext.initInternal()方法
                                                                    - super.initInternal(); StandardContext.initInternal()调用父类ContainerBase.initInternal() 它会创建startStopExecutor 并调用父类LifecycleMBeanBase.initInternal(); 这里会将容器托管到JMX
                                                                    - this.addLifecycleListener(new TldConfig()); 添加TldConfig监听
                                                                - setStateInternal(LifecycleState.INITIALIZED, null, false); // 更新组件生命周期状态为LifecycleState.INITIALIZED
                                                                    - ...
                                                                        - contextConfig.lifecycleEvent() contextConfig AFTER_INIT_EVENT生命周期事件处理
                                                                            - contextConfig.init(); context初始化阶段,context属性配置 tomcat提供的默认配置添加到context实例 完成对应的 每个web应用项目的配置解析(web.xml)
                                                                                - createContextDigester()
                                                                                - contextDigester.getParser();
                                                                                - contextConfig(contextDigester);  解析config.xml配置 E:\Java\apache-tomcat-7.0.82-01\conf\context.xml
                                                                                - createWebXmlDigester()
                                                                            - beforeStart() Lifecycle.BEFORE_START_EVENT状态
                                        - executor.init(); 初始化executors,即tomcat间可共享的线程池
                                        - connector初始化
                                            - connector.initInternal();
                                                - adapter = new CoyoteAdapter(this); 构建与指定连接器关联的新CoyoteAdapter
                                                - protocolHandler.setAdapter(adapter); 给 协议处理器 添加 adapter
                                                - protocolHandler.init(); 初始化具体协议类型,如Http11Protocol协议
                                                    - AbstractHttp11JsseProtocol.init()
                                                        - endpoint初始化之前,需要初始化ssl实现类 sslImplementation = SSLImplementation.getInstance(sslImplementationName); return new org.apache.tomcat.util.net.jsse.JSSEImplementation();
                                                        - super.init(),即AbstractProtocol.init() 1.注册组件JIoEndPoint;  2.endpoint.init() 设置work threads的数量,默认为200,并创建serverSocket对象
                                                            - abstractProtocol.bind() 设置线程数,网络连接数
                                                                - 初始化acceptor线程数量,默认1个; 初始化最大连接数,此值为server.xml的connector元素的属性MaxThreads值,(若不设置则)默认200
                                                                - abstractEndpoint.getMaxThreadsWithExecutor() 返回成员变量maxThreads=200
                                                                - abstractEndpoint.setMaxConnections(getMaxThreadsWithExecutor()); 设置最大连接数
                                                                    - initializeConnectionLatch(); 创建LimitLatch对象并初始化连接数 即 connectionLimitLatch = new LimitLatch(getMaxConnections());
                                                                - serverSocketFactory = new DefaultServerSocketFactory(this); 创建ServerSocketFactory
                                                                - serverSocket = serverSocketFactory.createSocket(getPort(),getBacklog()); 创建serverSocket
                                                - 初始化mapper listener mapperListener.init();
                        - 容器初始化完毕,LifecycleBase会将容器的状态更改为初始化完毕 setStateInternal(LifecycleState.INITIALIZED, null, false);
        - 3.daemon.start().即catalina.start() 运行各个组件,容器开始启动.
            - getServer().start() 启动Server 即standardServer.start(),由于未重写该方法. 所以会先调用父类LifecycleBase.start()
                - LifecycleBase.start()中 setStateInternal(LifecycleState.STARTING_PREP, null, false); // 启动前将状态设置为LifecycleState.STARTING_PREP
                - startInternal(); // 模板方法调用子类逻辑
                    - StandardServer.startInternal();中 1.发布configure_start事件 fireLifecycleEvent(CONFIGURE_START_EVENT, null);
                    - 2.设置状态为starting setState(LifecycleState.STARTING);  3.globalNamingResources.start(); globalNamingResources.start();
                    - 4.services[i].start(); 启动多个Service子容器. 略去LifecycleBase.start()的重复逻辑, 调用standardService.startInternal()
                        - standardService.startInternal()中 container.start(): 启动container,此时container为StandardEngine
                            - StandardEngine.startInternal()中 调用super.startInternal(), 即ContainerBase.startInternal()
                                - ContainerBase.startInternal()中 若配置了loader,manager,cluster,realm等,则会启动这些下属组件.  在engine,host,context等容器的启动逻辑都会调用该父类(ContainerBase)的此方法用于加载启动子容器. containerBase.startInternal()会向线程池 提交启动子容器的任务,并阻塞等待子容器启动的返回结果判定是否启动成功
                                    - ContainerBase.startInternal()中 getLoaderInternal()
                                        - Lock readLock = loaderLock.readLock(); readLock.lock(); try {     return loader; } finally {     readLock.unlock(); }
                                    - 若配置了realm组件,则启动 Realm realm = getRealmInternal();  if ((realm != null) && (realm instanceof Lifecycle))      ((Lifecycle) realm).start();
                                    - 若有子容器,则启动 Container children[] = findChildren();
                                    - results.add(startStopExecutor.submit(new StartChild(children[i]))); 提交启动子容器的任务,后续StandHost的操作会在新线程中完成
                                        - StartChild.call() class StartChild implements Callable<Void> StartChild类实现Callable,会执行覆写的call()方法
                                            - child.start(); 启动子容器,比如此处Engine的子容器就是Host 即调用standHost.start()
                                                - StandardHost.start() 使用父类LifecycleBase中的start()方法
                                                    - LifecycleBase.start()中
                                                        - LifecycleBase.start()中 setStateInternal(LifecycleState.STARTING_PREP, null, false); 触发before_start事件,即Host容器发布before_start事件, 相关监听器会接收到通知,执行相应逻辑,如HostConfig监听器
                                                            - HostConfig.lifecycleEvent() HostConfig实现LifecycleListener接口,在StandardHost启动时生命周期发生变化时, 会调用HostConfig的lifecycleEvent()对特定事件进行逻辑处理
                                                                - 调用HostConfig.beforeStart() BEFORE_START_EVENT
                                                                    - beforeStart() 会创建appBase和configBase路径所需的目录
                                                                        - 判断host.getCreateDirs(),对appBase和configBase进行mkdirs()
                                                        - lifecycleBase.startInternal(); 会调用子类StandardHost.startInternal()
                                                            - StandardHost.startInternal()中 Valve[] valves = getPipeline().getValves();
                                                                - 获取错误阀的阀名,即org.apache.catalina.valves.ErrorReportValve getErrorReportValveClass()
                                                                - 若有错误阀名,尝试遍历所有阀找出这个class类 StandardPipline.getValues() 通过value.getNext()循环遍历将所有Value成数组返回
                                                                - 若没有找到,则反射创建实例,并添加到pipeline中
                                                            - super.startInternal(); 调用ContainerBase.startInternal()新起线程启动子容器(即Host的Context子容器)
                                                                - ContainerBase.startInternal()中 results.add(startStopExecutor.submit(new StartChild(children[i]))); 启动StandardContext!!!!!!后续子节点都是Context容器的操作
                                                                    - 调用StandardContext.start(), 由于该类未重写start(), 所以实际上调用父类lifecycleBase.start()
                                                                        - lifecycleBase.start()中 若是LifecycleState.NEW状态
                                                                        - LifecycleBase.setStateInternal(LifecycleState.STARTING_PREP, null, false); 设置LifecycleState.STARTING_PREP状态,即before_start
                                                                            - 调用ContextConfig.beforeStart(); // 在context启动前触发,用于更新Context的docBase属性 和 解决web目录锁的问题
                                                                        - LifecycleBase.startInternal();
                                                                            - 调用子类StandardContext.startInternal() 完成对web应用的初始化工作
                                                                                - StandardContext.startInternal()里经过一系列操作,将状态变更为CONFIGURE_START_EVENT standardContext.fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null); 发布CONFIGURE_START_EVENT事件,contextConfig监听以完成servlet创建
                                                                                    - contextConfig.configureStart(); web应用初始化.解析web.xml文件, 创建wrapper,Filter,ServletContextListener等.
                                                                                        - contextConfig.webConfig()
                                                                                            - webXml.configureContext(context); 解析web.xml,将webXml对象设置给context
                                                                                                - Lin1388 webXml.configureContext(context); 解析servlet,将Servlet包装成Wrapper
                                                                                                    - context.createWrapper()
                                                                                                    - wrapper.setServletClass(servlet.getServletClass()); 将wrapper与servlet绑定
                                                                                                    - context.addChild(wrapper); 将wrapper添加到context中
                                                                                                        - containerBase.addChildInternal(child);
                                                                                                            - child.start(); 即standardWraper.start()
                                                                                                                - Wrapper容器 StandardWrapper.start()
                                                                        - LifecyclesetStateInternal(LifecycleState.STARTED, null, false); 设置LifecycleState.STARTED状态,即after_start
                                                                            - 调用context.setDocBase(originalDocBase);
                                                                        - containerBase.threadStart(); 启动Context层级的后台任务进程.Cluster后台任务(包括部署变更检测,心跳).Pipeline中Value的后台任务处理(如果有定时处理任务)
                                                                - ContainerBase.startInternal()中 setState(LifecycleState.STARTING); 设置容器状态为STARTING,此时会触发START_EVENT生命周期事件.即start事件
                                                                    - 调用HostConfig.start(); Host启动时触发,完成服务器启动过程中的 Web应用部署. 需要 Host的deployOnstartup="true"才会在服务器启动时部署web应用. 
                                    - 若有管道,则启动 if (pipeline instanceof Lifecycle)     ((Lifecycle) pipeline).start();
                        - executor.start(); 启动service容器的多个线程池executors
                        - connector.start(); 启动service组件的多个connector
                            - connector.startInternal()
                                - protocolHandler.start(); 启动 协议处理器
                                    - endpoint.start();
                                        - createExecutor(); 创建endpoint私有的线程池,即ThreadPoolExecutor线程池
                                            - abstractEndpoint.createExecutor()
                                                - new TaskQueue(); 用来运行线程池执行器的任务队列,该类extends LinkedBlockingQueue<Runnable>  new TaskThreadFactory()  implements ThreadFactory 线程工厂,用于创建并返回线程  executor = new ThreadPoolExecutor() 根据前两者 创建线程池
                                        - initializeConnectionLatch(); 创建LimitLatch对象,之前init时已经创建.此处直接返回
                                        - startAcceptorThreads(); 创建多个Acceptors
                                            - getAcceptorThreadCount(); 获取acceptor线程数量,默认1
                                            - return new JIoEndpoint.Acceptor() implements Runnable; 创建JIoEndpoint
                                            - Thread t = new Thread(acceptors[i], threadName); 根据JIoEndpoint创建线程,且是守护线程
                                - mapperListener.start(); 启动 mapperListener
                                    - findDefaultHost(); 从engine中获取defaultHost并设置给mapper
                                        - 从engine中获取defaultHost并设置给mapper mapper.setDefaultHostName(defaultHost);
                                    - addListeners(engine);
                                        - container.addContainerListener(this); container.addLifecycleListener(this); addListeners(child); 其中this为engine,child为host.即给engine注册监听
                                    - registHost() 向mapper注册host及其下的context,wrapper
                                        - mapper.addHost(host.getName(), aliases, host);
                                        - registerContext((Context) container); 向mapper注册context
                                            - prepareWrapperMappingInfo(context, (Wrapper) container, wrappers);

bootstrap.init()

创建 commonClassLoader,和 两个子 类加载器 catalinaLoader 和 sharedLoader,当然都是 URLClassLoader 实例,加载 一些 Jar.

设置当前线程的上下文类加载器为 catalinaLoader

设置 Catalina 的 父类加载器为 sharedLoader

处理 start 命令

分为 load 和 start 两步

load

读取 conf/server.xml 配置,使用 digester 解析,组装对象.

server.init() 主要遍历 services,调用其 init() 方法
状态变更: LifecycleState.NEW -> LifecycleState.INITIALIZING -> initInternal() -> LifecycleState.INITIALIZED

service.init()
调用 engine.init(),初始化executor,遍历初始化 connectors

Connector.init()
创建 CoyoteAdapter
protocolHandler 关联 adapter
protocolHandler.init(),这里面会初始化 endpoint
mapperListener.init()

StandEngine.init()
engine,host,context,wrapper 都继承自 ContainerBase,ContainerBase里会起 startStopExecutor 线程池,这个线程池用于子容器启动,父容器会等待子容器启动完成.

start

Catalina.start()
调用 server.start()

StandardServer.start()
触发 CONFIGURE_START_EVENT 事件,设置自身的状态为 STARTING,遍历调用 services.start()

StandService.start()
设置状态为 STARTING,调用 engine.start(),excutors.start(),connector.start()

StandEngine.start()
会走父类 ContainerBase.startInternal(),在 ContainerBase 中,若配了 loader,manager, cluster, realm 则 启动.
然后就查找所有子容器,每个子容器都交由 startStopExecutor 线程池 执行 StartChild 的逻辑,调用 child.start().并通过 future.get() 阻塞等待所有子容器启动成功.
pipeline.start()
设置线程状态为 STARTING,触发 START_EVENT 生命周期事件.
启动一个 ContainerBackgroundProcessor 后台线程.

ContainerBase.startInternal()代码

@Override
protected synchronized void startInternal() throws LifecycleException {
    // Start our subordinate components, if any.启动下属组件
    Loader loader = getLoaderInternal();
    if ((loader != null) && (loader instanceof Lifecycle))// 若配置了loader则启动
        ((Lifecycle) loader).start();
    logger = null;
    getLogger();
    Manager manager = getManagerInternal();
    if ((manager != null) && (manager instanceof Lifecycle))
        ((Lifecycle) manager).start();
    Cluster cluster = getClusterInternal();
    if ((cluster != null) && (cluster instanceof Lifecycle))// 若配置了集群,则启动
        ((Lifecycle) cluster).start();
    Realm realm = getRealmInternal();
    if ((realm != null) && (realm instanceof Lifecycle))// 若配置了安全组件Realm,则启动
        ((Lifecycle) realm).start();
    DirContext resources = getResourcesInternal();
    if ((resources != null) && (resources instanceof Lifecycle))
        ((Lifecycle) resources).start();

    // Start our child containers, if any.启动子容器,如果有的话.
    Container children[] = findChildren();
    List<Future<Void>> results = new ArrayList<Future<Void>>();
    for (int i = 0; i < children.length; i++) { // 提交 启动子容器的任务.并阻塞当前线程等待执行结果
        results.add(startStopExecutor.submit(new StartChild(children[i]))); // 子容器使用 startStopExecutor 调用新线程来启动
    }

    boolean fail = false;
    for (Future<Void> result : results) { // 启动 多个子容器的执行结果
        try {
            result.get(); // 阻塞直到所有子容器启动完毕
        } catch (Exception e) {
            log.error(sm.getString("containerBase.threadedStartFailed"), e);
            fail = true;
        }

    }
    if (fail) {
        throw new LifecycleException(
                sm.getString("containerBase.threadedStartFailed"));
    }

    // Start the Valves in our pipeline (including the basic), if any.启动容器持有的Pipeline组件的Value.若有管道,则启动
    if (pipeline instanceof Lifecycle)
        ((Lifecycle) pipeline).start();

    // 设置容器状态为STARTING,此时会触发START_EVENT生命周期事件.
    setState(LifecycleState.STARTING);

    // Start our thread. 启动该层级的后台定时任务进程(不同容器调用,则启动不同容器的后台线程).用于处理如 Cluster 后台任务(包括部署变更检测,心跳).Realm 后台任务处理.Pipeline 中 Value 的后台任务处理(如果有定时处理任务)
    threadStart();

}

StandardHost.startInternal()
不存在errorValve则创建,调用 ContainerBase.startInternal() 启动子容器.子容器是在 HostConfig.deployXxx里通过host.addChild(context)添加进来的.

StandContext.startInternal()
创建 WebappLoader 并启动
触发 CONFIGURE_START_EVENT 事件,contextConfig 监听以完成 servlet 创建
遍历启动子容器
启动pipline
触发listener的各种事件
初始化filter
初始化servlets,调用 load-on-startup 的 servlet 的 init() 方法
遍历 wraper,调用 wrapper.load() 加载 wrapper

StandWrapper.startInternal()
没什么重要逻辑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FlyingZCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值