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