嵌入式Servlet容器启动原理 前面我们总结了Spring Boot中嵌入式Servlet容器自动配置原理,也提到了Spring Boot2.0版本中使用ServletWebServerFactoryConfiguration替换了EmbeddedServletContainerAutoConfiguration,那么什么时候创建嵌入式的Servlet容器工厂以及什么时候获取嵌入式的Servlet容器并启动Tomcat呢?我们进入到ServletWebServerFactoryConfiguration中查看。
获取嵌入式的Servlet容器从Spring Boot应用启动运行run()方法开始 以Tomcat为例,在new TomcatServletWebServerFactory()处打断点,以Debug方式运行。
我们发现第一步是从执行SpringBootRestfulcrudApplication的run()方法开始的。
Spring Boot刷新IOC容器 Spring Boot刷新IOC容器,创建IOC容器对象,并且初始化容器,创建容器中每一个组件。
并进行判断,如果是web应用就创建AnnotationConfigServletWebServerApplicationContext,否则就创建默认的AnnotationConfigApplicationContext。此处Spring Boot2.0中也进行了更新,将原来的AnnotationConfigEmbeddedWebApplicationContext替换为AnnotationConfigServletWebServerApplicationContext。
刷新刚创建好的IOC容器 调用refresh()方法刷新刚刚创建好的IOC容器。
web的IOC容器重写onRefresh()方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 @Override public void refresh () throws BeansException, IllegalStateException { synchronized (this .startupShutdownMonitor) { prepareRefresh(); ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); prepareBeanFactory(beanFactory); try { postProcessBeanFactory(beanFactory); invokeBeanFactoryPostProcessors(beanFactory); registerBeanPostProcessors(beanFactory); initMessageSource(); initApplicationEventMulticaster(); onRefresh(); registerListeners(); finishBeanFactoryInitialization(beanFactory); finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } destroyBeans(); cancelRefresh(ex); throw ex; } finally { resetCommonCaches(); } } }
web的IOC容器会创建嵌入式的Servlet容器 上一步会调用此处的createWebServer()方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private void createWebServer () { WebServer webServer = this .webServer; ServletContext servletContext = getServletContext(); if (webServer == null && servletContext == null ) { ServletWebServerFactory factory = getWebServerFactory(); 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(); }
获取嵌入式的Servlet容器工厂 从IOC容器中获取ServletWebServerFactory组件,然后TomcatServletWebServerFactory创建对象,触发上一篇我们讲到的后置处理器,获取所有的定制器来定制Servlet容器的相关配置。
1 ServletWebServerFactory factory = getWebServerFactory();
使用容器工厂获取嵌入式的Servlet容器 1 this .webServer = factory.getWebServer(getSelfInitializer());
嵌入式的Servlet容器创建对象并启动Servlet容器如Tomcat 先启动嵌入式的Servlet容器,再将IOC容器中剩下的没有创建的对象获取得到,IOC容器启动创建嵌入式的Servlet容器。