编程语言
首页 > 编程语言> > springboot源码(八)

springboot源码(八)

作者:互联网

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