ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

springboot源码(八)

2022-04-03 00:34:07  阅读:160  来源: 互联网

标签:springboot tomcat webServer 源码 Tomcat ex context new


springboot中嵌入tomcat原理分析

首先要了解tomcat本身,否则springboot内嵌tomcat就很难分析。关于tomcat的源码会后续更新。

本文主要先简单分析一下springboot内嵌tomcat的源码,深入了解以后再更新。

还是先从springboot的启动入口run()方法开始分析。。。。。。

public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        configureHeadlessProperty();
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
            configureIgnoreBeanInfo(environment);
            Banner printedBanner = printBanner(environment);
            //创建应用上下文
            context = createApplicationContext();
            exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
            prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//刷新应用上下文,完成spring容器的初始化,也会加载tomcat refreshContext(context); afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); } listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context; }

 

进入refreshContext()----》ServletWebServerApplicationContext.refreshContext()方法:

进入super.refresh()方法后,进入到spring的源码中了,在进入onRefreshContext()方法---》ServletWebServerApplicationContext.onRefreshContext()方法

@Override
    protected void onRefresh() {
        super.onRefresh();
        try {
//创建web实例 createWebServer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start web server", ex); } }

 

进入createWebServer()方法:

private void createWebServer() {
        WebServer webServer = this.webServer;
        ServletContext servletContext = getServletContext();
        if (webServer == null && servletContext == null) {
//获取webServer的工厂对象 ServletWebServerFactory factory = getWebServerFactory();
//获得具体的webServer对象------>TomcatWebServer this.webServer = factory.getWebServer(getSelfInitializer()); 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(); }

 

再看一下getWebServer()里的逻辑---》直接进入TomcatServletWebServerFactory.getWebServer()中

 

 

public WebServer getWebServer(ServletContextInitializer... initializers) {
        if (this.disableMBeanRegistry) {
            Registry.disableRegistry();
        }
//创建tomcat对象 Tomcat tomcat = new Tomcat(); File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat"); tomcat.setBaseDir(baseDir.getAbsolutePath());
//创建连接器 Connector connector = new Connector(this.protocol); connector.setThrowOnFailure(true);
//service关联连接器 tomcat.getService().addConnector(connector); customizeConnector(connector); tomcat.setConnector(connector); tomcat.getHost().setAutoDeploy(false);
//配置Engin configureEngine(tomcat.getEngine()); for (Connector additionalConnector : this.additionalTomcatConnectors) { tomcat.getService().addConnector(additionalConnector); } prepareContext(tomcat.getHost(), initializers);
//返回获取的TomcatWebServer对象 return getTomcatWebServer(tomcat); }

 

然后进入到getTomcatWebServer()方法中

protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
//直接创建,我们需要看构造方法 return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown()); }

 

TomcatWebServer的构造方法:

public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {
        Assert.notNull(tomcat, "Tomcat Server must not be null");
        this.tomcat = tomcat;
        this.autoStart = autoStart;
        this.gracefulShutdown = (shutdown == Shutdown.GRACEFUL) ? new GracefulShutdown(tomcat) : null;
//初始化 重点 initialize(); }

 

进入initialize()方法:

private void initialize() throws WebServerException {
        logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));
        synchronized (this.monitor) {
            try {
                addInstanceIdToEngineName();

                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();
                    }
                });

                // Start the server to trigger initialization listeners
//启动Tomcat通过发布事件触发一些Listener的初始化
this.tomcat.start(); //启动tomcat // We can re-throw failure exception directly in the main thread rethrowDeferredStartupExceptions(); try { ContextBindings.bindClassLoader(context, context.getNamingToken(), getClass().getClassLoader()); } catch (NamingException ex) { // Naming is not enabled. Continue } // Unlike Jetty, all Tomcat threads are daemon threads. We create a // blocking non-daemon to stop immediate shutdown startDaemonAwaitThread(); } catch (Exception ex) { stopSilently(); destroySilently(); throw new WebServerException("Unable to start embedded Tomcat", ex); } } }

 

进入start()方法:

public void start() throws LifecycleException {
        this.getServer();
        this.server.start();
    }

 

 到这儿后面的逻辑其实就是Tomcat自身启动的逻辑了。这就需要你的Tomcat基础了,到这SpringBoot启动是如何内嵌Tomcat容器的到这儿就结束了哦。

springboot源码大致流程也就结束了。后面会有一些细节补充的内容。

 

标签:springboot,tomcat,webServer,源码,Tomcat,ex,context,new
来源: https://www.cnblogs.com/bentuzi/p/16094932.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有