Spring boot has been introduced earlier. This article begins with what spring boot does in the startup process and how to complete a web project with so little code.
For others, we can ignore it first. Let's take a look at the main method of springboot
@SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }
What did you do here? An annotation, a static method of SpringApplication, these two steps complete all the steps of springboot project startup.
Now let's look at what we've done.
Annotation doesn't care about it first. Follow the spring application run method
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) { return run(new Class<?>[] { primarySource }, args); } public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) { return new SpringApplication(primarySources).run(args); }
You can see that these two static methods actually do the same thing: instantiate the SpringApplication object and call the run method. So at this time, we can write the startup class as follows
@SpringBootApplication public class DemoApplication { public static void main(String[] args) { // SpringApplication.run(DemoApplication.class, args); SpringApplication springApplication = new SpringApplication(DemoApplication.class); springApplication.run(args); } }
We can get an instance of spring application first, and then call the run method through the instance to continue to see the operation below.
public SpringApplication(Class<?>... primarySources) { this(null, primarySources); } public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.resourceLoader = resourceLoader; Assert.notNull(primarySources, "PrimarySources must not be null"); this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources)); this.webApplicationType = WebApplicationType.deduceFromClasspath(); setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); }
As you can see here, when you instantiate a SpringApplication object, you do a lot of things:
- Set resourceLoader to load resources. We can implement it ourselves and load external resources
- primarySources sets the primary loading source of the bean
- Webapplicationtype determines the startup mode. For WebApplicationType.deduceFromClasspath(), please note that webapplicationtype is an enumeration class. It determines the startup mode by judging whether there is a class in the current path. Currently, it supports three modes (NONE, SERVLET, REACTIVE)
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; }
- setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class)) is the context required to load spring startup
- Set up monitoring
- Set start main class
Here's a 4 / 5 / 6 step and a technical point, which will be explained in detail later
After these steps, load the resources needed to start a spin application!
Next is the run method. First, paste the code. At first glance, it's a long code. What's it all about.
/** * Run the Spring application and create and refresh a new ApplicationContext. * @param args args Application parameters (usually passed from the main Java method) * @return a running {@link ApplicationContext} */ public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>(); configureHeadlessProperty(); SpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting(); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); configureIgnoreBeanInfo(environment); Banner printedBanner = printBanner(environment); context = createApplicationContext(); exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[] { ConfigurableApplicationContext.class }, context); prepareContext(context, environment, listeners, applicationArguments, printedBanner); refreshContext(context); afterRefresh(context, applicationArguments); stopWatch.stop(); if (this.logStartupInfo) { new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch); } listeners.started(context); callRunners(context, applicationArguments); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, listeners); throw new IllegalStateException(ex); } try { listeners.running(context); } catch (Throwable ex) { handleRunFailure(context, ex, exceptionReporters, null); throw new IllegalStateException(ex); } return context; }
To be continued