本文采用知识共享 署名-相同方式共享 4.0 国际 许可协议进行许可。
访问 https://creativecommons.org/licenses/by-sa/4.0/ 查看该许可协议。
1) 监听器模式
SpringBoot 的监听器可以在程序运行中,通过捕获到感兴趣的事件而触发,从而对 ApplicationContext 或程序做一些事情。
首先先康康精简版的 SpringBoot 监听器模式,监听我们的天气事件:
1.1) 事件
public abstract class WeatherEvent {
public abstract String getWeather();
}
public class WeatherRainEvent extends WeatherEvent {
@Override
public String getWeather() {
return "Raining...";
}
}
public class WeatherSnowEvent extends WeatherEvent {
@Override
public String getWeather() {
return "Snowing...";
}
}
1.2) 监听器
public interface WeatherListener {
void onEvent(WeatherEvent event);
}
public class WeatherRainListener implements WeatherListener {
@Override
public void onEvent(WeatherEvent event) {
if (!(event instanceof WeatherRainEvent)) return;
System.out.println(event.getWeather());
}
}
public class WeatherSnowListener implements WeatherListener {
@Override
public void onEvent(WeatherEvent event) {
if (!(event instanceof WeatherSnowEvent)) return;
System.out.println(event.getWeather());
}
}
1.3) 广播器
public class WeatherBroadcast {
private final List<WeatherListener> listeners = new ArrayList<>();
public void broadcast(WeatherEvent event) {
listeners.forEach(listener -> listener.onEvent(event));
}
public void addListener(WeatherListener listener) {
listeners.add(listener);
}
public void removeListener(WeatherListener listener) {
listeners.remove(listener);
}
}
1.4) 测试
public class WeatherBroadcastTest {
public static void main(String[] args) {
WeatherRainListener weatherRainListener = new WeatherRainListener();
WeatherSnowListener weatherSnowListener = new WeatherSnowListener();
WeatherBroadcast weatherBroadcast = new WeatherBroadcast();
weatherBroadcast.addListener(weatherRainListener);
weatherBroadcast.addListener(weatherSnowListener);
WeatherRainEvent weatherRainEvent = new WeatherRainEvent();
WeatherSnowEvent weatherSnowEvent = new WeatherSnowEvent();
weatherBroadcast.broadcast(weatherRainEvent);
weatherBroadcast.broadcast(weatherSnowEvent);
}
}
2) 定义监听器
SpringBoot 中大致可分为两类监听器,SmartApplicationListener
和 ApplicationListener
- SmartApplicationListener: 可实现
supportsEventType
方法实现对多种事件复杂的监听。 - ApplicationListener: 可通过指定泛型,监听简单的单一事件。
SpringBoot 在运行中会产生下图中的事件,我们可以监听这些事件来实现我们的监听器:
public class FirstListener implements ApplicationListener<ApplicationStartedEvent> {
@Override
public void onApplicationEvent(ApplicationStartedEvent event) {
ConfigurableApplicationContext applicationContext = event.getApplicationContext();
System.out.println("FirstListener......");
}
}
public class SecondListener implements SmartApplicationListener {
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return eventType.isAssignableFrom(ApplicationStartedEvent.class)
|| eventType.isAssignableFrom(ApplicationFailedEvent.class);
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("SecondListener......");
}
}
3) 注入监听器
注入监听器的方法和注入初始化器差不多,也有三种方法
3.1) 定义 /META-INF/spring.factories 注入
如果翻阅 SpringBoot 源码会得知启动过程中会从 /META-INF/spring.factories
中取得监听器并执行,spring-boot.jar
和 spring-boot-autoconfigure.jar
中有此配置文件例子,我们可以参考它们的格式编写我们的 spring.factories
,放进 classpath 下的 META-INF 中:
# Application Listener, 需添加多个可用 ',' 分隔
org.springframework.context.ApplicationListener=\
cat.wars.course.multidb.listener.listener.FirstListener,\
cat.wars.course.multidb.listener.listener.SecondListener
3.2) 通过 SpringApplication 注入
通常我们的 SpringBoot 启动主函数是这样写的:
SpringApplication.run(Application.class, args);
可以拆分为两行:
SpringApplication application = new SpringApplication(Application.class);
application.run(args);
可以使用 SpringApplication.addListeners
方法添加我们的监听器
SpringApplication application = new SpringApplication(Application.class);
application.addListeners(new FirstListener());
application.addListeners(new SecondListener());
application.run(args);
3.3) 配置文件注入
spring-boot.jar 中的 spring.factories
中定义加载了 DelegatingApplicationListener
,其中会读取配置文件中 context.listener.classes
属性,所以我们还能通过定义配置文件注入。
context:
listener:
classes: cat.wars.course.multidb.listener.listener.FirstListener,cat.wars.course.multidb.listener.listener.SecondListener
4) 总结
SpringBoot 中至少有三种方法,可以注入我们定义的 Spring 监听器,分别是:
- 定义
/META-INF/spring.factories
注入 - 通过
SpringApplication
的addListeners
方法注入 - 通过配置文件中
context.listener.classes
属性注入