Springboot内置Tomcat运行流程图及源码

在这里插入图片描述
在这里插入图片描述

Tomcat生命周期:创建、初始化、运行、停止、销毁

调用流程
在这里插入图片描述
refresh,这里其实是spring的核心代码
在这里插入图片描述
这里
在这里插入图片描述
这是模板方法,看子类实现
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
AutoConfiguration有一个ServletWebServerFactoryAutoConfiguration会被加载进来(细节在我的SpringBoot自动装配中有)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
所以才会获得tomcat对应的工厂。
进入getWebServer(),有多种实现
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
细节的创建
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

创建服务器阶段(套娃)

  private void createWebServer() {
    
    
        //首次进来空的
        WebServer webServer = this.webServer;
        ServletContext servletContext = getServletContext();
        if (webServer == null && servletContext == null) {
    
    
            StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
            //获取tomcat对应工厂
            ServletWebServerFactory factory = getWebServerFactory();
            createWebServer.tag("factory", factory.getClass().toString());
            //工厂创建webServer
            this.webServer = factory.getWebServer(getSelfInitializer());
            createWebServer.end();
            getBeanFactory().registerSingleton("webServerGracefulShutdown",
                    new WebServerGracefulShutdownLifecycle(this.webServer));
            getBeanFactory().registerSingleton("webServerStartStop",
                    new WebServerStartStopLifecycle(this, this.webServer));
        }
        else if (servletContext != null) {
    
    
            try {
    
    
                getSelfInitializer().onStartup(servletContext);
            }
            catch (ServletException ex) {
    
    
                throw new ApplicationContextException("Cannot initialize servlet context", ex);
            }
        }
        initPropertySources();
    }



    /**
     * @Description:getWebServer
     * @Author: PABLO
     * @Date: 2022/5/16 22:34
     * @Params: [initializers]
     * @Return: org.springframework.boot.web.server.WebServer
     **/
    public WebServer getWebServer(ServletContextInitializer... initializers) {
    
    

        if (this.disableMBeanRegistry) {
    
    
            Registry.disableRegistry();
        }
        //创建Tomcat
        //Tomcat主要组件  server service connector container(engine host context wrapper servlet )
        Tomcat tomcat = new Tomcat();
        //创建本地临时目录 如C:\Users\29751\AppData\Local\Temp\tomcat.9000.4254207608449001881
        File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
        tomcat.setBaseDir(baseDir.getAbsolutePath());
        for (LifecycleListener listener : this.serverLifecycleListeners) {
    
    
            tomcat.getServer().addLifecycleListener(listener);
        }
        //创建Connector 默认协议HTTP1.1
        Connector connector = new Connector(this.protocol);
        connector.setThrowOnFailure(true);
        //往Server中的Service添加Connector,这里会创建server和service并绑定,而后在往service中添加connector
        tomcat.getService().addConnector(connector);
        //自定义tomcat参数
        //如extends TomcatEmbeddedServletContainerFactory后重写customizeConnector,设置超时时间、最大连接数等等
        //或使用ymal文件配置也可以自定义
        /*
        * # tomcat
            server:
              tomcat:
                # 最大线程数
                max-threads: 5
                # 最大连接数
                max-connections: 10
              port: 9090
        * */
        customizeConnector(connector);
        //tomcat设置Connector
        tomcat.setConnector(connector);
        //往HOST中设置自动部署标记值,getHost()中会创建engine,而后创建host,建立关联关系
        tomcat.getHost().setAutoDeploy(false);
        //设置pipeline的阀,处理请求会依次调用每个容器的每个阀,而后会继续调用下一个子容器...
        configureEngine(tomcat.getEngine());
        for (Connector additionalConnector : this.additionalTomcatConnectors) {
    
    
            tomcat.getService().addConnector(additionalConnector);
        }
        //给当前host创建一个context应用
        prepareContext(tomcat.getHost(), initializers);
        
        return getTomcatWebServer(tomcat);
    }


    protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
    
    
        /**
         * @Description: prepareContext
         * @Author: PABLO
         * @Date: 2022/5/16 23:07
         * @Params: [host, initializers]
         * @Return: void
         **/
        File documentRoot = getValidDocumentRoot();
        //创建容器,每个HOST中可以有多个context,每个context可以认为是一个应用,即我们的一个项目,webapp大家还记的吧
        TomcatEmbeddedContext context = new TomcatEmbeddedContext();
        if (documentRoot != null) {
    
    
            context.setResources(new TomcatServletWebServerFactory.LoaderHidingResourceRoot(context));
        }
        //设置初始值...
        context.setName(getContextPath());
        context.setDisplayName(getDisplayName());
        context.setPath(getContextPath());
        File docBase = (documentRoot != null) ? documentRoot : createTempDir("tomcat-docbase");
        context.setDocBase(docBase.getAbsolutePath());
        context.addLifecycleListener(new Tomcat.FixContextListener());
        context.setParentClassLoader((this.resourceLoader != null) ? this.resourceLoader.getClassLoader()
                : ClassUtils.getDefaultClassLoader());
        resetDefaultLocaleMapping(context);
        addLocaleMappings(context);
        try {
    
    
            context.setCreateUploadTargets(true);
        }
        catch (NoSuchMethodError ex) {
    
    
            // Tomcat is < 8.5.39. Continue.
        }
        configureTldPatterns(context);
        WebappLoader loader = new WebappLoader();
        loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName());
        loader.setDelegate(true);
        context.setLoader(loader);
        if (isRegisterDefaultServlet()) {
    
    
            addDefaultServlet(context);
        }
        if (shouldRegisterJspServlet()) {
    
    
            addJspServlet(context);
            addJasperInitializer(context);
        }
        context.addLifecycleListener(new TomcatServletWebServerFactory.StaticResourceConfigurer(context));
        ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);
        //将此context应用放入当前host
        host.addChild(context);
        //设置一些环境值
        configureContext(context, initializersToUse);
        //空实现,可扩展
        postProcessContext(context);
    }

初始化服务器阶段(套娃)

 /**
     * @Description:容器启动核心代码
     * @Author: PABLO
     * @Date: 2022/5/17 13:04
     * @Params: []
     * @Return: void
     **/
    private void initialize() throws WebServerException {
    
    
        //控制台打印
        logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));
        synchronized (this.monitor) {
    
    
            addInstanceIdToEngineName();
            //获取应用this.tomcat.getHost().findChildren())
            Context context = findContext();
            //添加生命周期监听器
            context.addLifecycleListener((event) -> {
    
    
                if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) {
    
    
                    // Remove service connectors so that protocol binding doesn't
                    // happen when the service is started.
                    removeServiceConnectors();
                }
            });
            //启动服务器并触发对应监听器
            //每个容器都有生命周期,从server开始依次启动
            this.tomcat.start();
        }
    }

    //server启动初始状态为NEW
    private volatile LifecycleState state = LifecycleState.NEW;
    /*
    * NEW(false, null), 新生状态
    INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),初始化中
    INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),初始化完毕
    STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),启动之前
    STARTING(true, Lifecycle.START_EVENT),启动中
    STARTED(true, Lifecycle.AFTER_START_EVENT),启动完成
    STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),停止之前
    STOPPING(false, Lifecycle.STOP_EVENT),正在停止
    STOPPED(false, Lifecycle.AFTER_STOP_EVENT),已经停止
    DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),正在销毁
    DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),已经销毁
    FAILED(false, null); 失败
    * */
    /**
     * @Description:容器启动核心代码
     * @Author: PABLO
     * @Date: 2022/5/17 13:04
     * @Params: []
     * @Return: void
     **/
    public final synchronized void start() {
    
    
        if (state.equals(LifecycleState.NEW)) {
    
    
            //套娃启动操作,每个容器都来一遍
            //最先是server-init,状态为new,进行初始化,状态为initializing,进行initInternal();
            //会调用server的initInternal()
            init();
        } else if (state.equals(LifecycleState.FAILED)) {
    
    
            stop();
        } else if (!state.equals(LifecycleState.INITIALIZED) &&
                !state.equals(LifecycleState.STOPPED)) {
    
    
            invalidTransition(Lifecycle.BEFORE_START_EVENT);
        }
    }
    /**
     * @Description: 初始化server的关键代码,server中初始化service
     * @Author: PABLO
     * @Date: 2022/5/17 13:12
     * @Params: []
     * @Return: void
     **/
    protected void initInternal() throws LifecycleException {
    
    
        // 初始化Service  核心代码,将service的new状态改为initializing,进行initInternal();
        for (Service service : services) {
    
    
            //会调用service的initInternal()
            service.init();
        }
    }
    /**
     * @Description: 初始化service的关键代码,如果engine为null,会先初始化engine
     * @Author: PABLO
     * @Date: 2022/5/17 13:15
     * @Params: []
     * @Return: void
     **/
    protected void initInternal() throws LifecycleException {
    
    
        //初始化engine,这时engine是空的,因为刚刚只初始化到了service
        if (engine != null) {
    
    
            //初始化engine,将new改为initializing,进行initInternal();和server和service不同的是,初始化后会将initializing状态改为initialized
            //调用engine的initInternal();
            engine.init();
        }

        //初始化映射器
        //web.xml中URL和servlet的映射关系,由该组件处理
        mapperListener.init();

        // 初始化engine后初始化连接器
        //而后初始化protocoHandler  endPoint逐层返回到server,整个容器初始化完毕..
        synchronized (connectorsLock) {
    
    
            for (Connector connector : connectors) {
    
    
                connector.init();
            }
        }
    }

启动服务阶段(套娃)

/**
 * @Description: 容器的初始化阶段和启动阶段
 * @Author: PABLO
 * @Date: 2022/5/17 13:59
 * @Params: []
 * @Return: void
 **/
public final synchronized void start() throws LifecycleException {
    
    
    //初始化阶段
    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);
    }

    //初始化阶段完毕,进入启动阶段
    setStateInternal(LifecycleState.STARTING_PREP, null, false);
    //套娃启动
    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);
    }
}

/**
 * @Description: 启动容器
 * @Author: PABLO
 * @Date: 2022/5/17 14:00
 * @Params: []
 * @Return: void
 **/
protected void startInternal() throws LifecycleException {
    
    
    //设置server状态为starting
    setState(LifecycleState.STARTING);
    //启动service、 engine
    synchronized (servicesLock) {
    
    
        for (Service service : services) {
    
    
            service.start();
        }
    }
}

注意:在onRefresh中只是创建和初始化好了tomcat,但并未启动,在finishRefresh()–>startBeans()中启动
在这里插入图片描述
在这里插入图片描述

おすすめ

転載: blog.csdn.net/GiantCrocodile/article/details/124810871