The repository address mentioned in this article: Demo-Springboot

The startup process of SpringBoot:

(1) Enter through the main entrance of the program;

② Create SpringApplication object;

③ Call the Run method in the SpringApplication object to start SpringBoot;

(1) Create SpringApplication object

You can break on the main configuration class and step through to see how SpringBoot is running

① Break a breakpoint on the main configuration class

2 Start the application using Debug

③ Use a debugging tool to get inside the method that creates the SpringApplication object

Initializers values are stored and called in the run method.

The obtained value for listenters, where the obtained value is stored and later called by the run method.

Composition of the SpringApplication class

public class SpringApplication {...// The run method creates a SpringApplication object by calling this method
    public SpringApplication(Class
       ... primarySources) {
        this(null, primarySources);
    }

    // Actually create the Application object constructor
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public SpringApplication(ResourceLoader resourceLoader, Class
       ... primarySources) {
        // Load and save the master configuration class
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        // Check whether the current application is a Web application
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        / / in the classpath lookup meta-inf/spring. All factories configuration ApplicationContextInitializer, then save
        setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        // Find meta-INF /spring.factories in the classpath to configure all applicationListeners
        setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        // Find the main program class that contains the main method in multiple configuration classes
        this.mainApplicationClass = deduceMainApplicationClass(); }... }Copy the code

SpringApplication creation process:

① Determine the current application type;

(2) to load and save all ApplicationContextInitializer (meta-inf/spring. Factoties);

Load and save all ApplicationLisenter (meta-INF/spring.Factories);

④ Get the main program class containing the main method from multiple configuration classes;

(2) The running mechanism of the RUN method

What it does: Run the Spring application and create and refresh the IoC container

SpringApplication classrunMethod composition

public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    configureHeadlessProperty();
    / / 1) get SpringApplicationRunListeners call getRunListeners method
    SpringApplicationRunListeners listeners = getRunListeners(args);
    / / callback all SpringApplicationRunListener starting method of objects
    listeners.starting();
    try {
        // Encapsulate the parameters
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        // 2) Call the prepareEnvironment method to prepare the environment required for the IoC container to run
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        configureIgnoreBeanInfo(environment);
        // Print the banner icon on the console
        Banner printedBanner = printBanner(environment);
        // 3) Call createApplicationContext to create the IoC container and determine the type of the IoC container
        context = createApplicationContext();
        // Exception report, which is printed when an exception occurs
        exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                                                         new Class[] { ConfigurableApplicationContext.class }, context);
        // 4) Call the prepareContext method to prepare the context, save the environment(IoC environment configuration information) to IoC
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        // 5) Call the refreshContext method to refresh the container, i.e. initialize the IoC container. Embedded Servlet containers are also created for Web applications
        refreshContext(context);
         // Call the afterRefresh method, which is empty and may be used by a SpringBoot late extension
        afterRefresh(context, applicationArguments);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
        }
        / / callback all SpringApplicationRunListener started method of objects
        listeners.started(context);
        // Call the callRunners method for the event callback
        callRunners(context, applicationArguments);
    }
    catch (Throwable ex) {
        / / called when an exception occurs SpringApplicationRunListener object failed method
        handleRunFailure(context, ex, exceptionReporters, listeners);
        throw new IllegalStateException(ex);
    }

    try {
        / / callback object all SpringApplicationRunListener running method, the IoC container has been created
        listeners.running(context);
    }
    catch (Throwable ex) {
        / / called when an exception occurs SpringApplicationRunListener object failed method
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
    }
    // The entire SpringBoot application is now started and returned to the IoC container
    return context;
}

// The run method called through the main configuration class we wrote actually returns the following run method
public static ConfigurableApplicationContext run(Class
        primarySource, String... args) {
    return run(newClass<? >[] { primarySource }, args); }// Enter the method, create the object and call the real run method
public static ConfigurableApplicationContext run(Class
       [] primarySources, String[] args) {
    return new SpringApplication(primarySources).run(args);
}

Copy the code

GetRunListeners in the SpringApplication class

/ / in the classpath meta-inf/spring. The listener SpringApplicationRunListeners factories
private SpringApplicationRunListeners getRunListeners(String[] args) { Class<? >[] types =newClass<? >[] { SpringApplication.class, String[].class };/ / get the listener SpringApplicationRunListeners
    return new SpringApplicationRunListeners(logger,
                                             getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
Copy the code

2) The prepareEnvironment method in the SpringApplication class, which is used to prepare the environment needed for the IoC container to run

// Prepare the environment required for the current IoC container to run
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
    // Create and configure the environment
    ConfigurableEnvironment environment = getOrCreateEnvironment();
    configureEnvironment(environment, applicationArguments.getSourceArgs());
    ConfigurationPropertySources.attach(environment);
    / / callback object all SpringApplicationRunListener environmentPrepared method; The environment is now ready
    listeners.environmentPrepared(environment);
    bindToSpringApplication(environment);
    // Convert if the container is a Web container
    if (!this.isCustomEnvironment) {
        environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
                                                                                               deduceEnvironmentClass());
    }
    ConfigurationPropertySources.attach(environment);
    // Return to the created environment
    return environment;
}
Copy the code

3) The createApplicationContext method in the SpringApplication class is used to create the IoC container

// This method is used to create IoC containers
protected ConfigurableApplicationContext createApplicationContext(a) { Class<? > contextClass =this.applicationContextClass;
    if (contextClass == null) {
        try {
            // Create different IoC containers depending on the type of project
            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); }}// Create IoC containers with reflection
    return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
Copy the code

4) The prepareContext method in the SpringApplication class is used to prepare the context

// This method is used to prepare the context by adding the previously prepared information to the IoC container
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
    context.setEnvironment(environment);
    postProcessApplicationContext(context);
    / / call applyInitializers method to obtain all ApplicationContextInitializer object and call the initialize method
    applyInitializers(context);
    / / callback object all SpringApplicationRunListener contextPrepared () method
    listeners.contextPrepared(context);
    if (this.logStartupInfo) {
        logStartupInfo(context.getParent() == null);
        logStartupProfileInfo(context);
    }
    // Add boot specific singleton beans
    ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
    beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
    if(printedBanner ! =null) {
        beanFactory.registerSingleton("springBootBanner", printedBanner);
    }
    if (beanFactory instanceof DefaultListableBeanFactory) {
        ((DefaultListableBeanFactory) beanFactory)
        .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
    }
    if (this.lazyInitialization) {
        context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
    }
    // Load the sources
    Set<Object> sources = getAllSources();
    Assert.notEmpty(sources, "Sources must not be empty");
    load(context, sources.toArray(new Object[0]));
    / / prepareContext completion callback after all SpringApplicationRunListener contextLoaded method
    listeners.contextLoaded(context);
}
Copy the code

4-1) SpringApplication applyInitializers method in class, obtain all ApplicationContextInitializer object and call the initialize method

/ / this method is a callback previously saved all ApplicationContextInitializer the initialize method.
/ / ApplicationContextInitializer object is SpringBoot when it starts to get and keep
@SuppressWarnings({ "rawtypes", "unchecked" })
protected void applyInitializers(ConfigurableApplicationContext context) {
    for(ApplicationContextInitializer initializer : getInitializers()) { Class<? > requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class); Assert.isInstanceOf(requiredType, context,"Unable to call initializer."); initializer.initialize(context); }}Copy the code

5) The refreshContext method in the SpringApplication class is used to refresh the container, that is, to initialize the IoC container, where all components are created, scanned, and loaded

private void refreshContext(ConfigurableApplicationContext context) {
    if (this.registerShutdownHook) {
        try {
            context.registerShutdownHook();
        }
        catch (AccessControlException ex) {
            // Not allowed in some environments.}}// Call the refresh method to refresh the IoC container
    refresh((ApplicationContext) context);
}
Copy the code

6) The callRunners method in the SpringApplication class, which retrieves all applicationRunners and CommandLineRunner from the IoC container for callbacks

private void callRunners(ApplicationContext context, ApplicationArguments args) {
    List<Object> runners = new ArrayList<>();
    // Get ApplicationRunner in the IoC container
    runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
    // Get CommandLineRunner in the IoC container
    runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    AnnotationAwareOrderComparator.sort(runners);
    for (Object runner : new LinkedHashSet<>(runners)) {
        // Call ApplicationRunner
        if (runner instanceof ApplicationRunner) {
            callRunner((ApplicationRunner) runner, args);
        }
        // Callback CommandLineRunner again
        if (runner instanceofCommandLineRunner) { callRunner((CommandLineRunner) runner, args); }}}Copy the code

The SpringApplication class runs the run method:

The starting method of callback all SpringApplicationRunListener object;

Encapsulate arguments into ApplicationArguments objects.

(3) preparing for the demands of the IoC container operation environment, the callback object all SpringApplicationRunListener environmentPrepare method;

④ Output the banner information (SpringBoot logo) to the console.

⑤ Create IoC container objects;

  • org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext(Web environment container)
  • org.springframework.context.annotation.AnnotationConfigApplicationContext(Default environment container)

⑥ Prepare the context; At this point the callback SpringApplicationRunListener contextPrepared method and contextLoaded method of objects

The refresh container, that is, the initial IoC container, is where all components are created, scanned, and loaded;

Today all the callback object SpringApplicationRunListener started method;

⑨ Calls the callRunner method of the SpringApplication object; The run methods of ApplicationRunner and CommandLineRunner are called back;

Attending all SpringApplicationRunListener object callback running method;

The entire SpringBoot application is now started and returned to the IoC container;

The core of the run method:

  • With the use of various listening mechanisms, when do we need to intervene and call the callback at the corresponding time
  • refreshContextMethod: Refresh of the container, where all components are scanned, created, and loaded. All the components that we configured to load into the IoC container are loaded here.

(3) Event monitoring mechanism

From the previous analysis of SpringBoot application startup and run method running process, we can note that the startup of SpringBoot and the creation of IoC container depend on listener callback, and the purpose of intervening SpringBoot application startup can be achieved by invoking the corresponding listener at the appropriate time.

Several important event callbacks in SpringBoot:

  • Configured in meta-INF/spring.Factories
    • ApplicationContextInitializer
    • SpringApplicationRunListener
  • Configured in an IOC container
    • ApplicationRunner
    • CommandLineRunner

1. Configure the listener in meta-INF /spring.factories

1.1 ApplicationContextInitializer interface:

Function: Used to initialize Spring’s callback interface

The composition of ApplicationContextInitializer interface:

public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {

    /**
	 * Initialize the given application context.
	 * @param applicationContext the application to configure
	 */
    void initialize(C applicationContext);

}
Copy the code

ApplicationContextInitializer interface inheritance relationship diagram:

We can implement this interface to view ApplicationContextInitializer listener callback

public class TestApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("ApplicationContextInitializer object the initialize method to run the... The container type is:+ applicationContext); }}Copy the code

1.2 SpringApplicationRunListener interface

Function: SpringApplication object run method runtime listener

The composition of SpringApplicationRunListener interface:

public interface SpringApplicationRunListener {

    /** * Called immediately when the run method has first started. Can be used for very * early initialization. */
    default void starting(a) {}/**
	 * Called once the environment has been prepared, but before the
	 * {@link ApplicationContext} has been created.
	 * @param environment the environment
	 */
    default void environmentPrepared(ConfigurableEnvironment environment) {}/**
	 * Called once the {@link ApplicationContext} has been created and prepared, but
	 * before sources have been loaded.
	 * @param context the application context
	 */
    default void contextPrepared(ConfigurableApplicationContext context) {}/**
	 * Called once the application context has been loaded but before it has been
	 * refreshed.
	 * @param context the application context
	 */
    default void contextLoaded(ConfigurableApplicationContext context) {}/**
	 * The context has been refreshed and the application has started but
	 * {@link CommandLineRunner CommandLineRunners} and {@link ApplicationRunner
	 * ApplicationRunners} have not been called.
	 * @param context the application context.
	 * @since2.0.0 * /
    default void started(ConfigurableApplicationContext context) {}/**
	 * Called immediately before the run method finishes, when the application context has
	 * been refreshed and all {@link CommandLineRunner CommandLineRunners} and
	 * {@link ApplicationRunner ApplicationRunners} have been called.
	 * @param context the application context.
	 * @since2.0.0 * /
    default void running(ConfigurableApplicationContext context) {}/**
	 * Called when a failure occurs when running the application.
	 * @param context the application context or {@code null} if a failure occurred before
	 * the context was created
	 * @param exception the failure
	 * @since2.0.0 * /
    default void failed(ConfigurableApplicationContext context, Throwable exception) {}}Copy the code

SpringApplicationRunListener interface inheritance relationship diagram:

We can implement this interface to view ApplicationContextInitializer listener callback

public class TestSpringApplicationRunListener implements SpringApplicationRunListener {

    // This constructor must be written or an error will be reported
    public TestSpringApplicationRunListener(SpringApplication springApplication, String[] args) {}@Override
    public void starting(a) {
        System.out.println("Starting method is invoked on the SpringApplicationRunListener class...");
    }

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
        Object osName = environment.getSystemProperties().get("os.name");
        System.out.println("EnvironmentPrepared method is invoked on the SpringApplicationRunListener class..." + osName);
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        System.out.println("ContextPrepared method is invoked on the SpringApplicationRunListener class...");
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        System.out.println("ContextLoaded method is invoked on the SpringApplicationRunListener class...");
    }

    @Override
    public void started(ConfigurableApplicationContext context) {
        System.out.println("Started method is invoked on the SpringApplicationRunListener class...");
    }

    @Override
    public void running(ConfigurableApplicationContext context) {
        System.out.println("Running method is invoked on the SpringApplicationRunListener class...");
    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        System.out.println("Failed method is invoked on the SpringApplicationRunListener class..."); }}Copy the code

We need to configure our custom listeners by creating a meta-INF /spring.factories file in the classpath

org.springframework.context.ApplicationContextInitializer=\
  cn.bruce.springboot06_theory.listener.TestApplicationContextInitializer

org.springframework.boot.SpringApplicationRunListener=\
  cn.bruce.springboot06_theory.listener.TestSpringApplicationRunListener
Copy the code

2. Configure the listener in the IOC container

2.1 ApplicationRunner

Function:

The ApplicationRunner interface consists of:

@FunctionalInterface
public interface ApplicationRunner {

    /**
	 * Callback used to run the bean.
	 * @param args incoming application arguments
	 * @throws Exception on error
	 */
    void run(ApplicationArguments args) throws Exception;

}
Copy the code

ApplicationRunner interface inheritance diagram:

We can implement the ApplicationRunner interface to see when it calls

// Inject into the container
@Component
public class TestApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("The run method of the ApplicationRunner object executes......"); }}Copy the code

2.2 CommandLineRunner

What it does: It can be used to apply the IoC container in Spring

CommandLineRunner consists of:

@FunctionalInterface
public interface CommandLineRunner {

    /**
	 * Callback used to run the bean.
	 * @param args incoming main method arguments
	 * @throws Exception on error
	 */
    void run(String... args) throws Exception;

}
Copy the code

Implement the CommandLineRunner interface to check the call timing

// Add to the container
@Component
public class TestCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("The run method of the CommandLineRunner object executes...... Parameters:"+ Arrays.asList(args)); }}Copy the code

3. Listener callback time after the SpringBoot application is started

The output of the console after implementing the above interface

Are called SpringApplicationRunListener starting method in the class of... Are called SpringApplicationRunListener environmentPrepared method in the class of... Windows 10 . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| | _) | | | | | | | (_ | |)))) 'there comes | |. __ _ - | | | _ _ - | | | _ \ __, | / / / / = = = = = = = = = | _ | = = = = = = = = = = = = = = = | ___ / / _ / _ / _ / : : Spring the Boot: : (1) v2.3.5. RELEASE) ApplicationContextInitializer object the initialize method to run the... The container type is: org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@2ef3eef9, Started on Thu Jan 01 08:00:00 contextPrepared method is invoked on the CST 1970 SpringApplicationRunListener class... The 2020-11-07 11:43:47. 18792-376 the INFO [the main] C.B.S.S pringboot06TheoryApplication: Starting Springboot06TheoryApplication on YOGA-S740 with PID 18792 (E:\workspace\workspace_idea03\demo-springBoot\springboot06_theory\target\classes started by Bruce in E:\workspace\workspace_idea03\ demo-springboot) 2020-11-07 11:43:47.389 INFO 18792 -- [main] c.b.s.Springboot06TheoryApplication : No active profile set, falling back to default profiles: The default contextLoaded method is invoked on the SpringApplicationRunListener class... The 2020-11-07 11:43:48. 18792-165 the INFO [main] O.S.B.W.E mbedded. Tomcat. TomcatWebServer: Tomcat initialized with port(s): 8080 (HTTP) 11:43:48 2020-11-07. 18792-171 the INFO [main] o.a pache, catalina. Core. StandardService: Starting the service [Tomcat] 2020-11-07 11:43:48. 171 INFO 18792 - [the main] org. Apache. Catalina. Core. StandardEngine: Starting Servlet engine: [Apache Tomcat/9.0.39] 2020-11-07 11:43:48.230 INFO 18792 -- [main] O.A.C.C.C. [Tomcat].[/] : Initializing Spring Embedded WebApplicationContext 2020-11-07 11:43:48.231 INFO 18792 -- [main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: Initialization Completed in 785 MS 2020-11-07 11:43:48.345 INFO 18792 -- [main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2020-11-07 11:43:48.470 INFO 18792 -- [main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (HTTP) with the context path '11:43:48 2020-11-07. 18792-477 the INFO [main] C.B.S.S pringboot06TheoryApplication: Started Springboot06TheoryApplication in 1.378 seconds (JVM running for 2.064) SpringApplicationRunListener started in class method is called... The run method of the ApplicationRunner object executes...... The run method of the CommandLineRunner object executes...... Parameters: [] running method is invoked on the SpringApplicationRunListener class...Copy the code

From the console output, we can see the SpringBoot application startup process and the callback listener timing:

(1) to createSpringApplicationObject;

1) Determine the current application type;

2) to load and save all ApplicationContextInitializer (meta-inf/spring. Factoties);

Load and save all ApplicationLisenter (meta-INF/spring.Factories);

4) Get the main program class containing the main method from multiple configuration classes;

② Run the Run method in the SpringApplication object;

1) all SpringApplicationRunListener object callback starting method;

2) Encapsulate arguments in ApplicationArguments objects;

3) preparing for the demands of the IoC container operation environment, the callback object all SpringApplicationRunListener environmentPrepare method;

4) Output banner information (SpringBoot logo) to the console;

5) Create IoC container objects;

  • org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext(Web environment container)
  • org.springframework.context.annotation.AnnotationConfigApplicationContext(Default environment container)

6) to the context, the callback SpringApplicationRunListener contextPrepared method and contextLoaded method of objects

7) Refresh the container, that is, initialize the IoC container, where all components are created, scanned, and loaded;

All 8) callback SpringApplicationRunListener object started method;

9) Call the callRunner method of the SpringApplication object; The run methods of ApplicationRunner and CommandLineRunner are called back;

All 10) callback object SpringApplicationRunListener running method;

The entire SpringBoot application is now started and the configured IoC container is returned.

(4) Customized starters

The basic principles of starter writing:

(1) Determine the dependencies required by the application scenario;

(2) Write automatic configuration and configure related scenarios;

(3) Configuration mode, introducing Starters to import automatic configuration;

1. Starter written mode

(1) The launcher module is an empty Jar file that provides only auxiliary dependency management, which may be used for auto-assembly or other class libraries;

② Write an automatic configuration module xxxAutoConfiguration;

③ The initiator depends on automatic configuration. You only need to introduce the Starter to automatically configure.

The starter naming convention:

  • Official naming:Prefix - Module name
    • The prefix:spring-boot-starter-
    • Mode:Spring - the boot - starter - module name
    • For example:spring-boot-starter-web,spring-boot-starter-jdbc
  • Custom naming method:Module name - suffix
    • The suffix:-spring-boot-starter
    • Mode:Module - spring - the boot - the starter
    • For example:mybatis-spring-boot-starter

2. Write automatic configuration:

Write automatic configuration classes

@configuration  // Specify that this class is a configuration class
@ConditationOnxxx // The auto-configuration class takes effect if the specified condition is true
@AutoConfigureAfter // Specify the order of the auto-configuration classes
@Bean // Add components to the container

@EnableConfigurationProperties  // Introduce the relevant xxxProperties configuration class to take effect and add it to the container
Copy the code

Write configuration property classes

@ConfigurationProperties // Write the configuration related to the xxxProperties configuration class binding
Copy the code

Automatically configure the loading of classes

Configure the auto-configuration classes that need to be loaded at startup in meta-INF/Spring.Factories. Such as:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
Copy the code

3. Define the Starters and test them

3.1 Writing the Initiator module

Create the demo-spring-boot-starter module, and import the starter module only as a dependency.

writingpom.xmlfile


      
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.bruce.starter</groupId>
    <artifactId>demo-spring-boot-starter</artifactId>
    <version>1.0 the SNAPSHOT</version>

    <dependencies>
        <! -- Introducing automatic configuration module -->
        <dependency>
            <groupId>cn.bruce.starter</groupId>
            <artifactId>demo-spring-boot-starter-autoconfigurer</artifactId>
            <version>0.0.1 - the SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>
Copy the code

3.2 Write the automatic configuration module

Write the automatic configuration module Demo-spring-boot-starter-configurer

(1) to modifypom.xmlfile


      
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.5. RELEASE</version>
		<relativePath/> <! -- lookup parent from repository -->
	</parent>

	<groupId>cn.bruce.starter</groupId>
	<artifactId>demo-spring-boot-starter-autoconfigurer</artifactId>
	<version>0.0.1 - the SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>demo-spring-boot-starter-configurer</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<! -- Introducing spring-boot-starter; Basic configuration of all starter -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter</artifactId>
		</dependency>
	</dependencies>

</project>
Copy the code

② Write configuration attribute classes

@ConfigurationProperties(prefix = "demo.test")
public class TestProperties {
    private String prefix;
    private String suffix;

    public String getPrefix(a) {
        return prefix;
    }

    public void setPrefix(String prefix) {
        this.prefix = prefix;
    }

    public String getSuffix(a) {
        return suffix;
    }

    public void setSuffix(String suffix) {
        this.suffix = suffix; }}Copy the code

③ Write services

public class TestService {
    TestProperties testProperties;

    public TestProperties getTestProperties(a) {
        return testProperties;
    }

    public void setTestProperties(TestProperties testProperties) {
        this.testProperties = testProperties;
    }

    public String testPrintString(String name) {
        return testProperties.getPrefix() + "-"+ name + testProperties.getSuffix(); }}Copy the code

④ Write the automatic configuration service class

@Configuration
@ConditionalOnWebApplication // The Web application takes effect
@EnableConfigurationProperties(TestProperties.class )
public class TestServiceAutoConfiguration {

    @Autowired
    TestProperties testProperties;

    @Bean
    public TestService testService(a) {
        TestService testService = new TestService();
        testService.setTestProperties(testProperties);
        returntestService; }}Copy the code

⑤ Write the Spring configuration file and configure automatic import

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  cn.bruce.starter.TestServiceAutoConfiguration
Copy the code

⑥ Use Maven to package the initiator module and automatic configuration module into JAR packages

1) Package the Demo-spring-boot-starter-Configurer module into a JAR package and install it in the warehouse

2) Package the Demo-spring-boot-starter module into a JAR package and install it in the warehouse

The Demo-spring-boot-starter module depends on the Demo-spring-boot-starter -configurer module. Therefore, pack the Demo-spring-boot-starter – Configurer module first

3.3 Using a custom starter

1. Import a custom starter dependency

<! -- Introducing custom starter -->
<dependency>
    <groupId>cn.bruce.starter</groupId>
    <artifactId>demo-spring-boot-starter</artifactId>
    <version>1.0 the SNAPSHOT</version>
</dependency>
Copy the code

② Write the configuration file

demo.test.prefix=this is
demo.test.suffix=good
Copy the code

③ Write the controller call

@RestController
public class TestController {

    @Autowired
    TestService testService;

    @GetMapping("/test")
    public String Test(a) {
        return testService.testPrintString("cat"); }}Copy the code