天天看點

springboot原理實戰(11) -- springboot擴充分析CommandLineRunner

文章目錄

  • ​​目錄​​
  • ​​一、ApplicationContextInitializer​​
  • ​​①使用步驟:​​
  • ​​②注冊方法3種:​​
  • ​​示範 1.app.addInitializers方式​​
  • ​​示範 2:通過配置項context.initializer.classes指定​​
  • ​​3.spring.factories機制(注冊listener監聽器也可以使用這種方式)​​
  • ​​二、CommandLineRunner​​
  • ​​①使用步驟:​​
  • ​​三、ApplicationRunner​​

目錄

本文章主要了解在spring容器執行refreshed之前的一個回調接口:ApplicationContextInitializer,

在容器啟動成功後的最後一步回調(類似開機自啟動)的接口:CommandLineRunner和ApplicationRunner。

腦圖如下:

springboot原理實戰(11) -- springboot擴充分析CommandLineRunner

一、ApplicationContextInitializer

該接口是接口是在spring容器執行refreshed之前的一個回調。

①使用步驟:

  • 1: 寫一個類: 實作AApplicationContextInitializer接口
  • 2: 注冊ApplicationContextInitializer

②注冊方法3種:

  • 1.app.addInitializers
  • 2:通過配置項context.initializer.classes指定
  • 3.可以通過spring.factories機制(注冊listener監聽器也可以使用這種方式)

示範 1.app.addInitializers方式

寫個實作類

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

在入口中注冊和調用:

@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();
    }
}      

測試

springboot原理實戰(11) -- springboot擴充分析CommandLineRunner

:

測試已經注入!

示範 2:通過配置項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,寫了2個實作類:

context.initializer.classes=com.springboot.demo8.MyAppliationContextInitializer,com.springboot.demo8.MyAppliationContextInitializer2      
springboot原理實戰(11) -- springboot擴充分析CommandLineRunner
@SpringBootApplication
public class Demo8Application {

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

運作結果ok:

springboot原理實戰(11) -- springboot擴充分析CommandLineRunner

3.spring.factories機制(注冊listener監聽器也可以使用這種方式)

建立一個項目intializer:

springboot原理實戰(11) -- springboot擴充分析CommandLineRunner
<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      

将該項目引入原來的項目:

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

測試:

@SpringBootApplication
public class Demo8Application {

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

運作結果:

springboot原理實戰(11) -- springboot擴充分析CommandLineRunner

結果顯示已經注入!!

二、CommandLineRunner

該接口是在容器啟動成功後的最後一步回調(類似開機自啟動),可以在應用啟動時列印一些東西之類的。

①使用步驟:

  • 1.寫一個類,實作CommandLineRunner 接口
  • 2 把該類納入到spring的容器管理中

    ​​

    ​ 注意:可以通過@Order注解或者Ordered接口來控制執行順序。order值小的優先​

    ​ 示範一下
@Order(1)
@Component
public class ServerSuccessReport implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        System.out.println("=====應用已經成功的啟動============" + Arrays.asList(args));
    }

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

    @Override
    public void run(String... args) throws Exception {
        System.out.println("=====應用啟動後的時間是:============"+ LocalDateTime.now().toString());
    }

}      

以上2個類都實作了CommandLineRunner 接口,并用@Compoent,并通過order控制優先級,值小的優先執行,注入spring:

測試下:

@SpringBootApplication
public class Demo8Application {

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

運作結果:

springboot原理實戰(11) -- springboot擴充分析CommandLineRunner

三、ApplicationRunner

CommandLineRunner,ApplicationRunner 差別

差別在于方法的參數不一樣

CommandLineRunner的參數是最原始的參數,沒有做任務處理

ApplicationRunner的參數是ApplicationArguments,是對原始參數做了進一步的封裝

舉例說明:

看下CommandLineRunner的擷取參數代碼:

@Component
public class ServerSuccessReport implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("=====應用已經成功的啟動============" + Arrays.asList(args));
    }
}      

看戲ApplicationRunner的擷取參數代碼:

import java.util.Arrays;
@Component
public class StartedApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("應用已經啟動,參數為:" + Arrays.asList(args.getSourceArgs()));
    }
}      

運作結果:

springboot原理實戰(11) -- springboot擴充分析CommandLineRunner

都擷取了程式的參數,這裡我們看不出來差別,繼續改造:

  • 先設定啟動參數:
  • springboot原理實戰(11) -- springboot擴充分析CommandLineRunner
  • ApplicationRunner 擷取的是一個ApplicationArguments對象,我們來通過參數對象列印看下:
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();
    }      

運作結果:

springboot原理實戰(11) -- springboot擴充分析CommandLineRunner

可以看到通過ApplicationArguments可以使用其提供的getOptionNames,getOptionValues方法很友善的擷取參數值,而CommandLineRunner 隻能擷取到​

​--myname=admin​

​這樣的字元串,我們擷取key或者value需要使用split切割很麻煩,而且ApplicationArguments還有好多實用的方法:

springboot原理實戰(11) -- springboot擴充分析CommandLineRunner

這就是CommandLineRunner,ApplicationRunner 差別 : 方法的參數類型不一樣.

本文講了主要是springboot容器2個常用接口:在spring容器執行refreshed之前的一個回調接口:ApplicationContextInitializer,

在容器啟動成功後的最後一步回調(類似開機自啟動)的接口:CommandLineRunner和ApplicationRunner,和這2個接口的差別.

個人微信公号:

搜尋: 怒放de每一天

不定時推送相關文章,期待和大家一起成長!!