springboot web - 启动(4) tomcat

2020-02-21 16:04:30来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

springboot web - 启动(4) tomcat

接第二篇

第二篇里面, 看到容器创建的是 AnnotationConfigServletWebServerApplicationContext 类型.

一 .类图

   

二. 构造

public GenericApplicationContext() {
  //创建 bean 工厂
this.beanFactory = new DefaultListableBeanFactory(); } public AnnotationConfigServletWebServerApplicationContext() {
  //创建读取器
this.reader = new AnnotatedBeanDefinitionReader(this);
  //创建扫描器
this.scanner = new ClassPathBeanDefinitionScanner(this); }

构造函数中, 创建了三个类, 并赋值给相应的属性.

 

三. 启动 tomcat 

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory);

            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);

            // Initialize message source for this context.
            initMessageSource();

            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            onRefresh();

            // Check for listener beans and register them.
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                        "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

这里我主要是想要了解tomcat启动, 所以一些方法, 就先不看.

 onRefresh() 方法执行的是 ServletWebServerApplicationContext 的方法.

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

createWebServer() 方法中, 会创建 Tomcat 类.

private void createWebServer() {
    WebServer webServer = this.webServer;
  //当前进来, servletContext 为null ServletContext servletContext
= getServletContext(); if (webServer == null && servletContext == null) {
     //创建了 TomcatServletWebServerFactory ServletWebServerFactory factory
= getWebServerFactory();
     //创建 Tomcat
this.webServer = factory.getWebServer(getSelfInitializer()); } else if (servletContext != null) { try { getSelfInitializer().onStartup(servletContext); } catch (ServletException ex) { throw new ApplicationContextException("Cannot initialize servlet context", ex); } } initPropertySources(); }

getWebServer方法里面, 就创建了 Tomcat 类, 并对其进行一些配置操作.

@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
  //创建 Tomcat Tomcat tomcat
= new Tomcat(); File baseDir = (this.baseDirectory != null ? this.baseDirectory : createTempDir("tomcat")); tomcat.setBaseDir(baseDir.getAbsolutePath()); Connector connector = new Connector(this.protocol); tomcat.getService().addConnector(connector); customizeConnector(connector); tomcat.setConnector(connector); tomcat.getHost().setAutoDeploy(false); configureEngine(tomcat.getEngine()); for (Connector additionalConnector : this.additionalTomcatConnectors) { tomcat.getService().addConnector(additionalConnector); } prepareContext(tomcat.getHost(), initializers);
  //这里会创建 TomcatWebServer 实例, 并返回
return getTomcatWebServer(tomcat); }

这里的 protocol 是有一个默认值的:

public static final String DEFAULT_PROTOCOL = "org.apache.coyote.http11.Http11NioProtocol";

private String protocol = DEFAULT_PROTOCOL;

可以看到, 这里默认使用的是 同步非阻塞io协议


getTomcatWebServer()
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
    return new TomcatWebServer(tomcat, getPort() >= 0);
}

在创建 TomcatWebServer 的时候, 就会启动 Tomcat

public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
    Assert.notNull(tomcat, "Tomcat Server must not be null");
    this.tomcat = tomcat;
    this.autoStart = autoStart;
    initialize();
}

private void initialize() throws WebServerException {
    TomcatWebServer.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
            this.tomcat.start();

            // 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();
            throw new WebServerException("Unable to start embedded Tomcat", ex);
        }
    }
}

(未完待续...) 

 

 

 


原文链接:https://www.cnblogs.com/elvinle/p/12342860.html
如有疑问请与原作者联系

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:@JsonFormat与@DateTimeFormat注解的使用

下一篇:Redis5.x五种数据类型常见命令