One, foreword

  • Springboot source code parsing is a big project, line by line to study the code, can be boring, and not easy to stick to.
  • We do not pursue big and complete, but try to study a small knowledge point every time, and eventually together, this is our Springboot source tube leopard series.

Ii. Project type

In this section we discuss how the SpringBoot project automatically loads the ApplicationContext implementation class.

  • Previous Spring projects, which were xmL-loaded beans, used the XmlWebApplicationContext implementation class
  • Later appeared in the form of annotation, basic use AnnotationConfigWebApplicationContext implementation class
  • And then reactive

So which one does Springboot use?

Three, source code interpretation

Conclusion: SpringBoot determines the type selection based on the class.

public SpringApplication(ResourceLoader resourceLoader, Class<? >... primarySources) { ... this.webApplicationType = WebApplicationType.deduceFromClasspath(); . }Copy the code
  • Let’s start with the constructor of the SpringApplication
  • The constructor has a bit of code inside it that determines the type

Let’s look at the types first:

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; }Copy the code
  • If the Jersey and MVC dispatcherHandlers do not exist, it is reactive. If the Jersey and MVC dispatcherHandlers do not exist, it is reactive
  • The second cycle, there is no Servlet or ConfigurableWebApplicationContext is none
  • What remains is the familiar SERVLET

With the type determined, we look at the SpringApplication’s run method:

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

The ApplicationContext implementation class is defined in 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); }Copy the code

Load different classes according to type:

  • If it is the SERVLET: AnnotationConfigServletWebServerApplicationContext
  • If it is REACTIVE:

AnnotationConfigReactiveWebServerApplicationContext

  • default:AnnotationConfigApplicationContext

At this point, it’s clear that if you want a different project type, add the corresponding JAR package, and SpringBoot automatically selects the corresponding ApplicationContext implementation class for you

For a normal Web project:

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

Reactive:

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

For non-Web projects:

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

Welcome to pay attention to the public number: Fengji, more technical learning to share.