catalog
Project creation
Here we use IDE to create projects. When the scaffold is completed, I'm going to get another project to create the project according to the scaffold structure.
Here I use the IntelliJ IDE. First, we click a new project on the top left, then select Spring Initializr and JDK version. Here I use JDK 1.8 locally. Click Next
Then we start with a simple configuration project, where we mainly need to change the Group and Artifact. Here's not only the left side of Maven after your project, but also your project name.
Then choose dependency. Note that there are many people here who choose Lombok. Yes, I would also use Lombok programming if I created a project. But this time I want to build a universal scaffolding project. Lombok limits my version span, so I don't choose Lombok.
After creation, the IDE will automatically pull the required dependency package for you. After pulling, it is recommended to execute the maven command to build the project a little bit to ensure that there is no problem. Finally, it's running XXXApplication.java File to run the service. When you look at a log like this, it means that your project has been successfully created.
Interpretation of spring boot project architecture
The basic requirements of a basic spring boot project are as follows
- pom file of Maven project: mainly used to introduce the dependency of SpringBoot
- XXXApplication.java : This is the startup class of SpringBoot. Basically, you can run directly through IDE or execute Java jar after packaging.
- Configuration file: the configuration file of SpringBoot, which can be used to configure various required parameters. It's a bit similar to the previous xml, but it's greatly simplified. The specific configuration and loading order are not explained here. You can go to other articles
- Test class: and XXXApplication.java In contrast, it is the main entry to the test class
SpringBoot startup process
Next, understand the spring boot process by reading the source code.
Execution entry
Every SpringBoot service has one XXXApplication.java The entry class for. It provides a main method to start the service.
public static void main(String[] args) { SpringApplication.run(BasebootApplication.class, args); }
In fact, it's also implemented SpringApplication.run method. And pass some required parameters into the entry class.
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); }
As you can see from here, actually, the startup of SpringBoot is actually instantiating a SpringApplication, and then invoke the run method to start. So we will continue to explore the instantiation of spring application
SpringApplication instantiation
Entering the instantiation method of this class, we can see the following code. We can find that this is actually the process of preparing the environment. Here is a point to illustrate:
public SpringApplication(Class<?>... primarySources) { this((ResourceLoader)null, primarySources); } public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) { this.sources = new LinkedHashSet(); this.bannerMode = Mode.CONSOLE; this.logStartupInfo = true; this.addCommandLineProperties = true; this.addConversionService = true; this.headless = true; this.registerShutdownHook = true; this.additionalProfiles = new HashSet(); this.isCustomEnvironment = false; this.lazyInitialization = false; // Resource initialization resource loader is null this.resourceLoader = resourceLoader; // Assert that the main load resource class cannot be null, otherwise an error will be reported Assert.notNull(primarySources, "PrimarySources must not be null"); // Initialize and de duplicate the main load resource class collection this.primarySources = new LinkedHashSet(Arrays.asList(primarySources)); // Infer the current WEB application type // It is worth noting that this section mainly judges whether our application is a normal servlet or a WebFlux service (responsive service). I post a code below this.webApplicationType = WebApplicationType.deduceFromClasspath(); // Set up application line initializer // Interestingly, we will formally initialize the initializers that are often used in our projects. this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class)); // Set up a listener this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); // Infer main entry application class this.mainApplicationClass = this.deduceMainApplicationClass(); }
Judgment implementation of WebApplicationType. As you can see here, spring boot uses ClassUitls to determine the type.
static WebApplicationType deduceFromClasspath() { if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) { return REACTIVE; } else { String[] var0 = SERVLET_INDICATOR_CLASSES; int var1 = var0.length; for(int var2 = 0; var2 < var1; ++var2) { String className = var0[var2]; if (!ClassUtils.isPresent(className, (ClassLoader)null)) { return NONE; } } return SERVLET; } }
Spring application running
After the successful initialization of SpringApplication, we start to execute the run method to run our application.
public ConfigurableApplicationContext run(String... args) { // Start timing monitor StopWatch stopWatch = new StopWatch(); stopWatch.start(); // Initialize application context and exception report collection ConfigurableApplicationContext context = null; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); // Set system properties` java.awt.headless `The default value is: true this.configureHeadlessProperty(); // Create and start all Spring run listeners and publish application start events SpringApplicationRunListeners listeners = this.getRunListeners(args); listeners.starting(); Collection exceptionReporters; try { // Initialize default application parameter class ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // Prepare the Spring environment based on the running listener and the initialized application parameters ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); this.configureIgnoreBeanInfo(environment); // Create Banner printing class according to the environment Banner printedBanner = this.printBanner(environment); // Create an application context, which can never be more familiar context = this.createApplicationContext(); // Prepare exception report exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context); // Prepare application context this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); // Refresh the application context. When this step is completed, the SpringBoot application is basically started this.refreshContext(context); // Post processing of application context refresh this.afterRefresh(context, applicationArguments); // Stop timing monitoring class stopWatch.stop(); // Output log if (this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); } // Publish application context start completion event listeners.started(context); // Execute all Runner runners this.callRunners(context, applicationArguments); } catch (Throwable var10) { this.handleRunFailure(context, var10, exceptionReporters, listeners); throw new IllegalStateException(var10); } try { // Publish application context ready event listeners.running(context); return context; } catch (Throwable var9) { this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null); throw new IllegalStateException(var9); } }
At this point, the start-up process of spring boot has been implemented. We have access to our own apps.
appendix
Project directory: https://blog.csdn.net/turkeym4/article/details/106761043
Project address: https://gitee.com/turkeymz/baseboot