0
点赞
收藏
分享

微信扫一扫

20-SpringBoot事件监听

20-SpringBoot事件监听

SpringBoot事件监听

Java中的事件监听机制定义了以下几个角色:

①事件:Event,继承 java.util.EventObject 类的对象

②事件源:Source ,任意对象Object

③监听器:Listener,实现 java.util.EventListener 接口 的对象

SpringBoot 在项目启动时,会对几个监听器进行回调,我们可以实现这些监听器接口,在项目启动时完成一些操作。

  • ApplicationContextInitializer、
  • SpringApplicationRunListener、
  • CommandLineRunner、
  • ApplicationRunner

案例

1.创建一个基础项目 springboot-listener


20-SpringBoot事件监听_接口

下面我们来编写实现监听器接口。

2.实现监听器接口

  • ApplicationContextInitializer、
  • SpringApplicationRunListener、
  • CommandLineRunner、
  • ApplicationRunner

20-SpringBoot事件监听_zookeeper_02

2.1 实现 ApplicationContextInitializer

package com.lijw.springbootlistener.listener;

import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationContextInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("ApplicationContextInitializer initialize...");
}
}

2.2 实现 SpringApplicationRunListener

package com.lijw.springbootlistener.listener;

import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.stereotype.Component;

import java.time.Duration;

@Component
public class MySpringApplicationRunListener implements SpringApplicationRunListener {

@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
System.out.println("SpringApplicationRunListener starting..");
}

@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
System.out.println("SpringApplicationRunListener environmentPrepared..");
}

@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("SpringApplicationRunListener contextPrepared");
}

@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("SpringApplicationRunListener contextLoaded");
}

@Override
public void started(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("SpringApplicationRunListener started");
}

@Override
public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("SpringApplicationRunListener ready");
}

@Override
public void running(ConfigurableApplicationContext context) {
System.out.println("SpringApplicationRunListener running");
}

@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("SpringApplicationRunListener failed");
}
}

2.3 实现 CommandLineRunner

package com.lijw.springbootlistener.listener;

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner run");
}
}

2.4 实现 ApplicationRunner

package com.lijw.springbootlistener.listener;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner run");
}
}

3.测试验证


20-SpringBoot事件监听_接口_03

也就说明:MyApplicationRunner和MyCommandLineRunner都是当项目启动后执行,一般我们可以将缓存预热之类的操作放到这里执行。

那么另外的两个监听器要怎么才会启动监听呢?这个先不急,我们来看看 MyApplicationRunner和MyCommandLineRunner 的参数怎么用。

4. MyApplicationRunner和MyCommandLineRunner的参数使用

4.1 打印 MyApplicationRunner和MyCommandLineRunner 的 args 参数

// 项目启动后执行
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner run... args: " + Arrays.asList(args));
}
}
// 项目启动后执行
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner run... args: " + Arrays.asList(args.getSourceArgs()));
}
}

打印信息如下:


20-SpringBoot事件监听_spring boot_04

可以看到,现在传递的参数为空数组。

如果需要传递参数,则是可以配置在项目的启动命令上。

4.2 配置项目的启动命令


20-SpringBoot事件监听_接口_0520-SpringBoot事件监听_spring boot_06

此时,再启动服务,我们来看看传递的参数如下:


20-SpringBoot事件监听_java_07

5.配置使用 MyApplicationContextInitializer 和 MySpringApplicationRunListener 的监听器

5.1 需要在 META-INF/spring.factories 配置注册两个实现类


20-SpringBoot事件监听_接口_08

org.springframework.context.ApplicationContextInitializer=com.lijw.springbootlistener.listener.MyApplicationContextInitializer

org.springframework.boot.SpringApplicationRunListener=com.lijw.springbootlistener.listener.MySpringApplicationRunListener

此时,我们再执行启动服务,可以发现报错如下:


20-SpringBoot事件监听_spring_09

// main方法中出现异常,异常由于接口MySpringApplicationRunListener实现类报错
Exception in thread "main" java.lang.IllegalArgumentException: Cannot instantiate interface org.springframework.boot.SpringApplicationRunListener : com.lijw.springbootlistener.listener.MySpringApplicationRunListener
at org.springframework.boot.SpringApplication.createSpringFactoriesInstances(SpringApplication.java:456)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:438)
at org.springframework.boot.SpringApplication.getRunListeners(SpringApplication.java:426)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:293)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301)
at com.lijw.springbootlistener.SpringbootListenerApplication.main(SpringbootListenerApplication.java:10)
// MySpringApplicationRunListener报错的类型为缺少方法,缺少了 <init>(org.springframework.boot.SpringApplication, [Ljava.lang.String;) 也就是缺少了 构造器方法。
Caused by: java.lang.NoSuchMethodException: com.lijw.springbootlistener.listener.MySpringApplicationRunListener.<init>(org.springframework.boot.SpringApplication, [Ljava.lang.String;)
at java.lang.Class.getConstructor0(Class.java:3082)
at java.lang.Class.getDeclaredConstructor(Class.java:2178)
at org.springframework.boot.SpringApplication.createSpringFactoriesInstances(SpringApplication.java:451)
... 6 more

Process finished with exit code 1

在查看如何设置构造器的方法上,我们可以查看这个接口的其他实现类:


20-SpringBoot事件监听_spring boot_10

5.2 MySpringApplicationRunListener的使用要添加构造器


20-SpringBoot事件监听_zookeeper_1120-SpringBoot事件监听_zookeeper_12

package com.lijw.springbootlistener.listener;

import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;

import java.time.Duration;

public class MySpringApplicationRunListener implements SpringApplicationRunListener {


public MySpringApplicationRunListener(SpringApplication application, String[] args){

}

@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
System.out.println("SpringApplicationRunListener starting..");
}

@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
System.out.println("SpringApplicationRunListener environmentPrepared..");
}

@Override
public void contextPrepared(ConfigurableApplicationContext context) {
System.out.println("SpringApplicationRunListener contextPrepared");
}

@Override
public void contextLoaded(ConfigurableApplicationContext context) {
System.out.println("SpringApplicationRunListener contextLoaded");
}

@Override
public void started(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("SpringApplicationRunListener started");
}

@Override
public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
System.out.println("SpringApplicationRunListener ready");
}

@Override
public void running(ConfigurableApplicationContext context) {
System.out.println("SpringApplicationRunListener running");
}

@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
System.out.println("SpringApplicationRunListener failed");
}
}

执行打印的日志:

SpringApplicationRunListener starting..
SpringApplicationRunListener environmentPrepared..

. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.6.4)

ApplicationContextInitializer initialize...
SpringApplicationRunListener contextPrepared
2022-02-27 08:54:55.785 INFO 15164 --- [ main] c.l.s.SpringbootListenerApplication : Starting SpringbootListenerApplication using Java 1.8.0_91 on regalli-NB0 with PID 15164 (D:\javaProject\maven-practice01\springboot-listener\target\classes started by lijw in D:\javaProject\maven-practice01)
2022-02-27 08:54:55.785 INFO 15164 --- [ main] c.l.s.SpringbootListenerApplication : No active profile set, falling back to 1 default profile: "default"
SpringApplicationRunListener contextLoaded
2022-02-27 08:54:56.255 INFO 15164 --- [ main] c.l.s.SpringbootListenerApplication : Started SpringbootListenerApplication in 0.9 seconds (JVM running for 1.838)
SpringApplicationRunListener started
ApplicationRunner run... args: [name=libai, age=32]
CommandLineRunner run... args: [name=libai, age=32]
SpringApplicationRunListener ready

Process finished with exit code 0



举报

相关推荐

0 条评论