嵌入式web容器
种类
spring-boot支持使用jetty、netty、tomcat、undertow作为嵌入式web容器
获取web容器实例
public void refresh() throws BeansException, IllegalStateException { synchronized(this.startupShutdownMonitor) { this.prepareRefresh(); ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory(); this.prepareBeanFactory(beanFactory); try { this.postProcessBeanFactory(beanFactory); this.invokeBeanFactoryPostProcessors(beanFactory); this.registerBeanPostProcessors(beanFactory); this.initMessageSource(); this.initApplicationEventMulticaster(); this.onRefresh(); this.registerListeners(); this.finishBeanFactoryInitialization(beanFactory); this.finishRefresh(); } catch (BeansException var9) { if (this.logger.isWarnEnabled()) { this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9); } this.destroyBeans(); this.cancelRefresh(var9); throw var9; } finally { this.resetCommonCaches(); } } } protected void onRefresh() throws BeansException { } protected void finishRefresh() { this.clearResourceCaches(); this.initLifecycleProcessor(); this.getLifecycleProcessor().onRefresh(); this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this))); LiveBeansView.registerApplicationContext(this); }
  spring-framework初始化的步骤如上,而spring-boot的嵌入式web容器实例化在
spring-boot支持两种容器方案,一种为阻塞式的servlet,另一种为非阻塞的reactive,spring-boot在启动时会根据classpath下文件推断当前使用的是何种容器方案,从而使用
onRefresh方法里进行。spring-boot支持两种容器方案,一种为阻塞式的servlet,另一种为非阻塞的reactive,spring-boot在启动时会根据classpath下文件推断当前使用的是何种容器方案,从而使用
ReactiveWebServerApplicationContext或ServletWebServerApplicationContext类实例,它们都继承了spring-framework的GenericWebApplicationContext类,并重写了onRefresh方法。servlet方案容器的实例化
ServletWebServerApplicationContext.java
 
@Override protected void onRefresh() { super.onRefresh(); try { createWebServer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start web server", ex); } } 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(); } protected ServletWebServerFactory getWebServerFactory() { // Use bean names so that we don't consider the hierarchy String[] beanNames = getBeanFactory() .getBeanNamesForType(ServletWebServerFactory.class); if (beanNames.length == 0) { throw new ApplicationContextException( "Unable to start ServletWebServerApplicationContext due to missing " + "ServletWebServerFactory bean."); } if (beanNames.length > 1) { throw new ApplicationContextException( "Unable to start ServletWebServerApplicationContext due to multiple " + "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames)); } return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class); }
  容器类型存在成员变量
上一段提到需要从beanFactory中获取实现了
webServer中,在实例化容器前,会先判断webServer是否已经被实例化,webServer是一个接口,所有的嵌入式容器启动类都实现了这个接口。getWebServerFactory方法会从beanFactory中获取实现了ServletWebServerFactory接口的类实例,通过其getWebServer方法可以实例化具体的web容器实例并放入实现了WebServer的类中返回。上一段提到需要从beanFactory中获取实现了
ServletWebServerFactory接口的类实例,这个类实例来自于spring-boot提供的auto-configuration功能,专用的嵌入式容器jar包会自动配置ServletWebServerFactory的实现。servlet方案容器的运行
@Override protected void finishRefresh() { super.finishRefresh(); WebServer webServer = startWebServer(); if (webServer != null) { publishEvent(new ServletWebServerInitializedEvent(webServer, this)); } } private WebServer startWebServer() { WebServer webServer = this.webServer; if (webServer != null) { webServer.start(); } return webServer; }
  上文说到容器的实例化在
该方法直接调用了
onRefresh方法进行,而容器的启动则是在finishRefresh方法进行,同样的,ServletWebServerApplicationContext类重写了GenericWebApplicationContext类的finishRefresh方法。该方法直接调用了
webServer的start方法启动容器。就这样,项目容器的WebServer接口实现类便会被启动,具体的启动方法因容器而异,具体启动的实现可参考NettyWebServer、TomcatWebServer、JettyWebServer、UndertowWebServer、UndertowServletWebServer,spring-boot提供了这几种嵌入式容器启动的实现。reactive方案容器的实例化
@Override protected void onRefresh() { super.onRefresh(); try { createWebServer(); } catch (Throwable ex) { throw new ApplicationContextException("Unable to start reactive web server", ex); } } private void createWebServer() { ServerManager serverManager = this.serverManager; if (serverManager == null) { this.serverManager = ServerManager.get(getWebServerFactory()); } initPropertySources(); } protected ReactiveWebServerFactory getWebServerFactory() { // Use bean names so that we don't consider the hierarchy String[] beanNames = getBeanFactory() .getBeanNamesForType(ReactiveWebServerFactory.class); if (beanNames.length == 0) { throw new ApplicationContextException( "Unable to start ReactiveWebApplicationContext due to missing " + "ReactiveWebServerFactory bean."); } if (beanNames.length > 1) { throw new ApplicationContextException( "Unable to start ReactiveWebApplicationContext due to multiple " + "ReactiveWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames)); } return getBeanFactory().getBean(beanNames[0], ReactiveWebServerFactory.class); }
  与servlet方案的容器实例化类似,reactive方案的容器实例化仅仅将获取容器实例的接口从
ServletWebServerFactory变成了ReactiveWebServerFactory,嵌入式容器jar包会提供实现了ServletWebServerFactory接口的bean。reactive方案容器的运行
@Override protected void finishRefresh() { super.finishRefresh(); WebServer webServer = startReactiveWebServer(); if (webServer != null) { publishEvent(new ReactiveWebServerInitializedEvent(webServer, this)); } } private WebServer startReactiveWebServer() { ServerManager serverManager = this.serverManager; ServerManager.start(serverManager, this::getHttpHandler); return ServerManager.getWebServer(serverManager); } public static void start(ServerManager manager, Supplier<HttpHandler> handlerSupplier) { if (manager != null && manager.server != null) { manager.handler = handlerSupplier.get(); manager.server.start(); } }
与servlet方案容器的实现一致,直接调用start方法运行即可。
本文来自博客园,作者:l-coil,转载请注明原文链接:https://www.cnblogs.com/l-coil/p/13018813.html
 
   
            
            
            
            
            
            
            
            
            
            
            
           
 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号