一、前言

  • Springboot源码解析是一件大工程,逐行逐句的去钻研代码,会很干燥,也不容易坚持下去。
  • 咱们不谋求大而全,而是试着每次去钻研一个小知识点,最终聚沙成塔,这就是咱们的springboot源码管中窥豹系列。

二、我的项目类型

这一节咱们先讨论一下springboot我的项目的怎么主动加载applicationcontext实现类的。

  • 以前的spring的我的项目,都是xml加载bean,罕用的都是XmlWebApplicationContext实现类
  • 起初呈现注解的模式,根本用AnnotationConfigWebApplicationContext实现类
  • 起初又呈现响应式编程reactive

那springboot用的是哪一种呢?

三、源码解读

先说论断:对于类型的抉择,springboot是依据class来判断的。

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {    ...    this.webApplicationType = WebApplicationType.deduceFromClasspath();        ...}
  • 咱们从SpringApplication的构造函数开始看起
  • 构造函数外面有段代码:是确定类型的

咱们先看类型:

private static final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",        "org.springframework.web.context.ConfigurableWebApplicationContext" };private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";static WebApplicationType deduceFromClasspath() {    if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)            && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {        return WebApplicationType.REACTIVE;    }    for (String className : SERVLET_INDICATOR_CLASSES) {        if (!ClassUtils.isPresent(className, null)) {            return WebApplicationType.NONE;        }    }    return WebApplicationType.SERVLET;}
  • 第一段if,如果存在reactive包的DispatcherServlet,同时不存在jersey和mvc的DispatcherHandler,就是REACTIVE
  • 第二段循环,不存在Servlet或者ConfigurableWebApplicationContext,就是none
  • 剩下的就是咱们相熟的SERVLET

类型确定之后,咱们看SpringApplication的run办法:

public ConfigurableApplicationContext run(String... args) {            ...    try {        ...        context = createApplicationContext();                ...    } catch (Throwable ex) {                ...    }        ...    return context;}

ApplicationContext实现类就是在createApplicationContext()外面确定的

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

依据类型加载不同的class:

  • 如果是SERVLET:AnnotationConfigServletWebServerApplicationContext
  • 如果是REACTIVE:

AnnotationConfigReactiveWebServerApplicationContext

  • default:AnnotationConfigApplicationContext

至此,高深莫测了,想要不同的我的项目类型,增加对应的jar包,springboot主动帮你抉择对应的ApplicationContext实现类

如果是一般的web我的项目:

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

如果是reactive我的项目:

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-webflux</artifactId></dependency>

如果是非web我的项目:

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter</artifactId></dependency>

欢送关注公众号:丰极,更多技术学习分享。