springboot源码解析-管中窥豹系列之web服务器(七)

Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去。

我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot源码管中窥豹系列。

 简介

二、web服务器

以前的的spring项目或者springmvc项目都需要一个web服务器,tomcat,或者其它的

使用springboot之后,我们不再需要配置web服务器,因为springboot帮我们集成了

今天我们来分析一下源码,看看在哪里实现的,知其然知其所以然

三、源码分析

还是从SpringApplication的run方法开始看

不熟悉的可以看之前的文章:springboot源码解析-管中窥豹系列之总体结构(一)

SpringApplication.java public ConfigurableApplicationContext run(String... args) { ... try { ... refreshContext(context); ... } catch (Throwable ex) { ... } ... return context; }

接着进入到 refreshContext(context) 里面

AbstractApplicationContext.java @Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { ... try { ... // Initialize other special beans in specific context subclasses. onRefresh(); ... } catch (BeansException ex) { ... } finally { ... } } }

进入到 onRefresh() 方法

protected void onRefresh() throws BeansException { // For subclasses: do nothing by default. }

注意这个是一个protected方法,我们进入到子实现里面

具体用的哪个context,请看之前的文章:springboot源码解析-管中窥豹系列之项目类型(二)

public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context." + "annotation.AnnotationConfigApplicationContext"; public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot." + "web.servlet.context.AnnotationConfigServletWebServerApplicationContext"; public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframework." + "boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext"; protected ConfigurableApplicationContext createApplicationContext() { Class<?> contextClass = this.applicationContextClass; if (contextClass == null) { try { switch (this.webApplicationType) { case SERVLET: contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS); break; case REACTIVE: contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS); break; default: contextClass = Class.forName(DEFAULT_CONTEXT_CLASS); } } catch (ClassNotFoundException ex) { throw new IllegalStateException( "Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex); } } return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass); }

最常用的就是普通web项目,我们看这一个

我们到org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext里面找 onRefresh() 方法

没找到,在父类ServletWebServerApplicationContext里面找到了

ServletWebServerApplicationContext.java @Override protected void onRefresh() { super.onRefresh(); try { 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) { 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(); }

用的工厂模式,先找到工厂getWebServerFactory()

再用工厂生成webServer, factory.getWebServer(getSelfInitializer())

先看看 getWebServerFactory() 这个方法

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

获取唯一的工厂:ServletWebServerFactory,多了少了都不行

在哪加载进springboot的呢?

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure</artifactId> <scope>compile</scope> </dependency>

spring-boot-starter-web里面是包含了spring-boot-starter依赖的

spring-boot-starter里面包含了spring-boot-autoconfigure依赖

spring-boot-autoconfigure里面有一个类:ServletWebServerFactoryConfiguration

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjyjs.html