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.