Spring boot Principle Practice (11) -- spring boot extension analysis CommandLineRunner

Article directory

Catalog

This article focuses on a callback interface before the spring container performs the refreshed: ApplicationContextInitializer,
The interface of the last callback (similar to startup) after the container starts successfully: CommandLineRunner and ApplicationRunner.
The brain map is as follows:

1, ApplicationContextInitializer

The interface is a callback before the spring container performs the refreshed.

① Use steps:

  • 1: Write a class: implement aaapplicationcontextinitializer interface
  • 2: Register ApplicationContextInitializer

② There are three registration methods:

  • 1.app.addInitializers
  • 2: Specified by configuration item context.initializer.classes
  • 3. You can use the spring.factories mechanism (you can also use this method to register the listener listener)

Demo 1.app.addInitializers

Write an implementation class

public class MyAppliationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("bean count: " + applicationContext.getBeanDefinitionCount());
    }
}

Register and call in the portal:

@SpringBootApplication
public class Demo8Application {
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Demo8Application.class);
        app.addInitializers(new MyAppliationContextInitializer());
        ConfigurableApplicationContext context = app.run(args);
        context.close();
    }
}

test
:
Test injected!

Demo 2: specify by configuration item context.initializer.classes

public class MyAppliationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("bean count: " + applicationContext.getBeanDefinitionCount());
    }

}
public class MyAppliationContextInitializer2 implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println(applicationContext.getDisplayName());
   }
}

application.properties, two implementation classes are written:

context.initializer.classes=com.springboot.demo8.MyAppliationContextInitializer,com.springboot.demo8.MyAppliationContextInitializer2

@SpringBootApplication
public class Demo8Application {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Demo8Application.class);
        ConfigurableApplicationContext context = app.run(args);
        context.close();
    }

Run result ok:

3.spring.factories mechanism (this can also be used to register listener listeners)

Create a new project intializer:

<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.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springboot</groupId>
    <artifactId>intializer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>intializer</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

</project>

public class EchoAppliationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        System.out.println("=========EchoAppliationContextInitializer==========");
    }

}

intializer\src\main\resources\META-INF\spring.factories:

org.springframework.context.ApplicationContextInitializer=com.springboot.intializer.EchoAppliationContextInitializer

Introduce the project into the original project:

 <dependency>
   <groupId>com.springboot</groupId>
     <artifactId>intializer</artifactId>
     <version>0.0.1-SNAPSHOT</version>
 </dependency>

Test:

@SpringBootApplication
public class Demo8Application {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Demo8Application.class);
        ConfigurableApplicationContext context = app.run(args);
        context.close();
    }
}

Operation result:

The result shows that it has been injected!!

2, CommandLineRunner

This interface is the last callback after the container is started successfully (similar to startup), and it can print something when the application is started.

① Use steps:

  • 1. Write a class to implement the CommandLineRunner interface
  • 2. Put this class into spring's container management
    Note: the execution order can be controlled through the @ order annotation or the Ordered interface. Priority of low order value
    Demonstrate
@Order(1)
@Component
public class ServerSuccessReport implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("=====App started successfully============" + Arrays.asList(args));
    }

}

@Order(2)
@Component
public class ServerStartedReport implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("=====The time after the app starts is:============"+ LocalDateTime.now().toString());
    }

}

The above two classes all implement the CommandLineRunner interface, and use @ component to control the priority through order, and implement the priority with small value, and inject spring:

Test:

@SpringBootApplication
public class Demo8Application {

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Demo8Application.class);
        ConfigurableApplicationContext context = app.run(args);
        context.close();
    }
 }

Operation result:

3, ApplicationRunner

Difference between commandlinerunner and applicationrunner
The difference is that the parameters of the method are different
The parameters of CommandLineRunner are the most original parameters, and no task processing has been done
The parameter of ApplicationRunner is ApplicationArguments, which further encapsulates the original parameter

For example:

Take a look at the command line runner's get parameter code:

@Component
public class ServerSuccessReport implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("=====App started successfully============" + Arrays.asList(args));
    }
}

To get the parameter code of ApplicationRunner:

import java.util.Arrays;
@Component
public class StartedApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("App started with parameters:" + Arrays.asList(args.getSourceArgs()));
    }
}

Operation result:

All parameters of the program have been obtained, and we can't see the difference here. Continue to transform:

  • Set the startup parameters first:

    ApplicationRunner gets an ApplicationArguments object. Let's print it through the parameter object to see:
    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(Demo8Application.class);
        ConfigurableApplicationContext context = app.run(args);
        ApplicationArguments arg = context.getBean(ApplicationArguments.class);
        System.out.println(arg.getSourceArgs().length);
        System.out.println(arg.getOptionNames());
        System.out.println(arg.getOptionValues("myname"));
        context.close();
    }

Operation result:

It can be seen that the getOptionNames and getOptionValues methods provided by ApplicationArguments can be used to conveniently get parameter values, while CommandLineRunner can only get strings such as -- myname=admin. We need to use split to get key or value, and there are many practical methods for ApplicationArguments:

This is the difference between commandlinerunner and applicationrunner: the parameter types of methods are different

This article mainly talks about two common interfaces of the spring boot container: a callback interface before the spring container performs the refreshed: ApplicationContextInitializer,
In the last step after the container starts successfully, call back the interface (similar to booting up from scratch): CommandLineRunner and ApplicationRunner, which are different from these two interfaces

Personal wechat Company No.:
Search: bloom every day
Push related articles from time to time, looking forward to growing with you!!

finish

246 original articles published, 29 praised, 70000 visitors+
Private letter follow

Tags: Spring Maven SpringBoot Apache

Posted on Tue, 17 Mar 2020 00:40:17 -0700 by MarcAndreTalbot