SpringBoot startup process and project creation

Posted by Dilbert137 on Tue, 16 Jun 2020 09:28:26 +0200

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

  1. pom file of Maven project: mainly used to introduce the dependency of SpringBoot
  2. XXXApplication.java : This is the startup class of SpringBoot. Basically, you can run directly through IDE or execute Java jar after packaging.
  3. 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
  4. 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

Topics: Spring SpringBoot Java Lombok