SpringBoot 监听器解析

221 阅读4分钟

仅供个人学习记录使用

来自于慕课网《图解+仿写 新手都能学懂的SpringBoot源码课》课程

Reference:全方位深入解析最新版SpringBoot源码-慕课网实战 (imooc.com)

章节目录

一、监听器模式介绍

二、系统监听器介绍

三、监听时间触发机制

四、自定义监听器实战

五、章节回顾

监听器模式介绍

image.png

监听器模式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);
}

系统事件

系统事件介绍

image.png

事件发送顺序

image.png

  • 框架一启动 starting

  • 环境准备完成 environmentPrepared 系统属性、其他属性提交到容器内

  • contextInitialized Springboot 启动并准备好上下文,加载任何 bean 之前

  • prepared 应用上下文创建完毕,bean 还未完全加载完成

  • started Springboot 把单例 bean 实例化完成,但是还未调用 ApplicationRunner 和 CommandLineRunner

  • ready ApplicationRunner 和 CommandLineRunner 运行完之后被调用

  • failed 失败或者错误

监听器注册

参考系统初始化器

image.png

image.png

监听事件触发机制

源码

image.png

image.png

SpringApplicationRunListeners 定义各个阶段事件的监听 监听器的内部实现与外部调用隔离

image.png

广播器广播事件

image.png

获取监听器列表流程

image.png

通用触发条件

image.png

监听器的触发

遍历调用监听器

image.png

获取支持的监听器列表:首先尝试从缓存获取,缓存不存在再进行计算

image.png

image.png

获取支持的监听器列表

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 方法判断当前事件来源是否为该监听器所感兴趣的事件来源

监听器执行

image.png

image.png

image.png

自定义监听器

实现方式

继承 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 接口区别