仅供个人学习记录使用
来自于慕课网《图解+仿写 新手都能学懂的SpringBoot源码课》课程
Reference:全方位深入解析最新版SpringBoot源码-慕课网实战 (imooc.com)
章节目录
一、监听器模式介绍
二、系统监听器介绍
三、监听时间触发机制
四、自定义监听器实战
五、章节回顾
监听器模式介绍
监听器模式demo
事件
public abstract class WeatherEvent {
public abstract String getWeather();
}
public class RainEvent extends WeatherEvent{
@Override
public String getWeather() {
return "rain";
}
}
public class SnowEvent extends WeatherEvent{
@Override
public String getWeather() {
return "snow";
}
}
监听器
public interface WeatherListener {
void onWeatherEvent(WeatherEvent event);
}
public class RainListener implements WeatherListener{
@Override
public void onWeatherEvent(WeatherEvent event) {
if (event instanceof RainEvent) {
System.out.println("hello" + event.getWeather());
}
}
}
public class SnowListener implements WeatherListener{
@Override
public void onWeatherEvent(WeatherEvent event) {
if (event instanceof SnowEvent) {
System.out.println("hello" + event.getWeather());
}
}
}
广播器
public interface EventMulticaster {
void multicastEvent(WeatherEvent event);
void addListener(WeatherListener weatherListener);
void removeListener(WeatherListener weatherListener);
}
public abstract class AbstractEventMulticaster implements EventMulticaster{
private List<WeatherListener> weatherListeners = new ArrayList<>();
@Override
public void multicastEvent(WeatherEvent event) {
doStart();
weatherListeners.forEach(i -> i.onWeatherEvent(event));
doEnd();
}
@Override
public void addListener(WeatherListener weatherListener) {
weatherListeners.add(weatherListener);
}
@Override
public void removeListener(WeatherListener weatherListener) {
weatherListeners.remove(weatherListener);
}
abstract void doStart();
abstract void doEnd();
}
public class WeatherEventMulticaster extends AbstractEventMulticaster{
@Override
void doStart() {
System.out.println("begin broadcast weather event");
}
@Override
void doEnd() {
System.out.println("end broadcast weather event");
}
}
测试类触发
public class Test {
public static void main(String[] args) {
WeatherEventMulticaster weatherEventMulticaster = new WeatherEventMulticaster();
RainListener rainListener = new RainListener();
SnowListener snowListener = new SnowListener();
weatherEventMulticaster.addListener(rainListener);
weatherEventMulticaster.addListener(snowListener);
weatherEventMulticaster.multicastEvent(new RainEvent());
weatherEventMulticaster.multicastEvent(new SnowEvent());
weatherEventMulticaster.removeListener(rainListener);
weatherEventMulticaster.multicastEvent(new RainEvent());
weatherEventMulticaster.multicastEvent(new SnowEvent());
}
}
监听器模式要素
-
事件
-
监听器
-
广播器
-
触发机制
SpringBoot 监听器实现 ApplicationListener
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
static <T> ApplicationListener<PayloadApplicationEvent<T>> forPayload(Consumer<T> consumer) {
return (event) -> {
consumer.accept(event.getPayload());
};
}
}
/**
* A tagging interface that all event listener interfaces must extend.
* @since JDK1.1
*/
public interface EventListener {
}
系统广播器实现 ApplicationEventMulticaster
public interface ApplicationEventMulticaster {
void addApplicationListener(ApplicationListener<?> listener);
void addApplicationListenerBean(String listenerBeanName);
void removeApplicationListener(ApplicationListener<?> listener);
void removeApplicationListenerBean(String listenerBeanName);
void removeApplicationListeners(Predicate<ApplicationListener<?>> predicate);
void removeApplicationListenerBeans(Predicate<String> predicate);
void removeAllListeners();
void multicastEvent(ApplicationEvent event);
void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}
系统事件
系统事件介绍
事件发送顺序
-
框架一启动 starting
-
环境准备完成 environmentPrepared 系统属性、其他属性提交到容器内
-
contextInitialized Springboot 启动并准备好上下文,加载任何 bean 之前
-
prepared 应用上下文创建完毕,bean 还未完全加载完成
-
started Springboot 把单例 bean 实例化完成,但是还未调用 ApplicationRunner 和 CommandLineRunner
-
ready ApplicationRunner 和 CommandLineRunner 运行完之后被调用
-
failed 失败或者错误
监听器注册
参考系统初始化器
监听事件触发机制
源码
SpringApplicationRunListeners 定义各个阶段事件的监听 监听器的内部实现与外部调用隔离
广播器广播事件
获取监听器列表流程
通用触发条件
监听器的触发
遍历调用监听器
获取支持的监听器列表:首先尝试从缓存获取,缓存不存在再进行计算
获取支持的监听器列表
protected boolean supportsEvent(ApplicationListener<?> listener, ResolvableType eventType, @Nullable Class<?> sourceType) {
GenericApplicationListener smartListener = listener instanceof GenericApplicationListener ? (GenericApplicationListener)listener : new GenericApplicationListenerAdapter(listener);
return ((GenericApplicationListener)smartListener).supportsEventType(eventType) && ((GenericApplicationListener)smartListener).supportsSourceType(sourceType);
}
判断是否是 GenericApplicationListener 类型,不是则执行 GenericApplicationListenerAdapter
public GenericApplicationListenerAdapter(ApplicationListener<?> delegate) {
Assert.notNull(delegate, "Delegate listener must not be null");
this.delegate = delegate;
this.declaredEventType = resolveDeclaredEventType(this.delegate);
}
resolveDeclaredEventType 方法为获取监听器所支持的事件泛型
supportsEventType 判断监听器是否监听该事件
public boolean supportsEventType(ResolvableType eventType) {
if (this.delegate instanceof SmartApplicationListener) {
Class<? extends ApplicationEvent> eventClass = eventType.resolve();
return eventClass != null && ((SmartApplicationListener)this.delegate).supportsEventType(eventClass);
} else {
return this.declaredEventType == null || this.declaredEventType.isAssignableFrom(eventType);
}
}
如果监听器是 SmartApplicationListener 类型,调用监听器自己定义的 supportsEventType 方法
如果不是 SmartApplicationListener 类型,判断监听器所支持的事件是否是当前所发生的事件
supportsEventType 为 true 接着判断 supportsSourceType
public boolean supportsSourceType(@Nullable Class<?> sourceType) {
return !(this.delegate instanceof SmartApplicationListener) || ((SmartApplicationListener)this.delegate).supportsSourceType(sourceType);
}
如果监听器不是 SmartApplicationListener 类型,直接返回 true
如果监听器是 SmartApplicationListener 类型,调用其自定义 supportsSourceType 方法
supportsSourceType 方法判断当前事件来源是否为该监听器所感兴趣的事件来源
监听器执行
自定义监听器
实现方式
继承 ApplicationListener 接口
public class FirstListener implements ApplicationListener<ApplicationStartedEvent> {
@Override
public void onApplicationEvent(ApplicationStartedEvent applicationStartedEvent) {
System.out.println("hello firstListener");
}
}
继承 SmartApplicationListener 接口
@Order(4)
public class FourthListener implements SmartApplicationListener {
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) {
return aClass.isAssignableFrom(ApplicationStartedEvent.class) || aClass.isAssignableFrom(ApplicationPreparedEvent.class);
}
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
System.out.println("hello fourthListener");
}
}
注册方式
一、resources 下 META-INF 文件夹下创建 spring.factories 文件
org.springframework.context.ApplicationListener = com.mooc.sb2.listener.FirstListener
二、SpringApplication addListeners 硬编码添加
SpringApplication springApplication = new SpringApplication(Sb2Application.class);
springApplication.addListeners(new SecondListener());
springApplication.run(args);
三、在resources 下 application.properties 文件中注册
context.listener.classes = com.mooc.sb2.listener.ThirdListener
Tips
-
实现 ApplicationListener 针对单一事件监听
-
实现 SmartApplicationListener 针对多种事件监听
-
Order 值越小越先执行
-
application.properties 中定义的优于其他方式
章节总结
-
监听器模式回顾:原理、要素、实现
-
监听器框架实现回顾:系统实现、框架事件发送顺序、SpringApplicationRunListener
-
监听事件触发机制回顾:监听器实现注册、获取感兴趣监听器列表、事件触发条件
-
自定义监听器回顾:实现方式、注意事项
相关面试题
-
介绍下监听器模式
-
SpringBoot 关于监听器相关的实现类有哪些
-
SpringBoot 有哪些框架事件以及他们的顺序
-
介绍下监听事件触发机制
-
如何自定义实现系统监听器及注意事项
-
实现 ApplicationListener 接口与 SmartApplicationListener 接口区别