spring boot -- startup configuration principle

spring boot – how the boot configuration works

1, @ SpringBootApplication annotation

  1. When we create a new project, the springboot application startup portal will appear, as shown below:
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Let's analyze the startup program. First, let's take a look at the @ SpringBootApplication annotation source code:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)

We will find that this annotation mainly includes@ SpringBootConfiguration@EnableAutoConfiguration ,
@ComponentScan has three core annotations. The analysis is as follows:

  • @The SpringBootConfiguration annotation indicates that this is a Configuration class that can be scanned by components, which is similar to @ Configuration in spring. It can be found from the following source code that its implementation is also based on @ Configuration annotation, but it is encapsulated by annotation;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
  • @EnableAutoConfiguration class is also a composite annotation, which mainly contains two core annotations @ AutoConfigurationPackage and @ Import({AutoConfigurationImportSelector.class}). The source code is as follows.
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})

(1) The source code of @ AutoConfigurationPackage is as follows. Its main function is to import all registered components into the container. The imported components are determined by the Registrar.

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};
}

Click the register class and find (String[])(new)
AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]) is mainly used to obtain the directory where the project main program starts.

(2) The following notes are about Automatic configuration principle of springBoot You can click the link to view the relevant knowledge.

2, SpringBoot runs the 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);
    }

As can be seen from the above source code, the execution process of springboot consists of two parts: one is the initialization of new SpringApplication () and the other is the run() method. These two parts are analyzed in detail below:

SpringApplication() initialization

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;
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }

From the above source code analysis, it mainly includes:

  • this.webApplicationType = WebApplicationType.deduceFromClasspath(); Judge the current application type. The deducefromclasspath () method is used to check whether a feature class exists in the current classpath, so as to judge whether the webApplication type is a servlet application or a Reactive application.
  • this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class)); Used to set the initializer. Will use the springFactoriesLoader to download from meta-inf / spring The factories class loads all applicable initializers.
  • this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); Used to set the listener, just like the initializer.
  • this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = this.deduceMainApplicationClass();
    }The main program startup class used to infer and set the startup of the main() method of the project.

run() method of the execution process of springboot

 public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();
        //(1) Used to get spring applicationrunlisteners during initialization and run them.
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        listeners.starting();

        Collection exceptionReporters;
        try {
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //(2) Pre configuration of the project operation environment.
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            Banner printedBanner = this.printBanner(environment);
            //(3) Pre configuration of project context ApplicationContext.
            context = this.createApplicationContext();
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }
//(4) The project running listener starts the configured application context ApplicationContext.
            listeners.started(context);
//(5) Call the program executor configured in the ApplicationContext of the application context.
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }

        try {
        //(6) The project running listener continuously runs the configured application context ApplicatioNContext
            listeners.running(context);
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }

Tags: Spring Spring Boot

Posted by waltonia on Wed, 04 May 2022 23:05:10 +0300