一、介绍下监听器模式?
核心组件:广播器、事件、监听器
所谓监听就是事件发生时,通过广播器持有的监听器列表,循环调用监听器的方法
事件源
#抽象事件
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 {
//@Autowired,map/list 借助Spring得能力也可以注入
private List<WeatherListener> listenerList;
@Override
public void multicastEvent(WeatherEvent event) {
doStart();
listenerList.forEach(i -> i.onWeatherEvent(event));
doEnd();
}
@Override
public void addListener(WeatherListener weatherListener) {
listenerList.add(weatherListener);
}
@Override
public void removeListener(WeatherListener weatherListener) {
listenerList.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");
}
}
可以看到,如果实际代码中要发送事件,必须持有一个EventMulticaster
的实现,然后调用相应的方法。这样做稍显麻烦,从Spring
的代码中可以学到一招。
@Component
public class WeatherRunListener {
@Autowired
private WeatherEventMulticaster eventMulticaster;
public void snow() {
eventMulticaster.multicastEvent(new SnowEvent());
}
public void rain() {
eventMulticaster.multicastEvent(new RainEvent());
}
}
这样,我们只需要持有WeatherRunListener
即可,想发送什么事件可以掉对应的方法。
掌握监听器的核心还是在于把握三要素。
二、SpringBoot关于监听器相关的实现类有哪些?
事件抽象及子类
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;
private final long timestamp;
public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}
public final long getTimestamp() {
return this.timestamp;
}
}
监听器抽象
#可以通过泛型指定自己感兴趣的类型
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
void onApplicationEvent(E event);
}
//看到下面的support方法,应该可以猜到这个是通过support方法来表明自己对哪些时间感兴趣
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
/**
* Determine whether this listener actually supports the given event type.
* @param eventType the event type (never {@code null})
*/
boolean supportsEventType(Class<? extends ApplicationEvent> eventType);
/**
* Determine whether this listener actually supports the given source type.
* <p>The default implementation always returns {@code true}.
* @param sourceType the source type, or {@code null} if no source
*/
default boolean supportsSourceType(@Nullable Class<?> sourceType) {
return true;
}
@Override
default int getOrder() {
return LOWEST_PRECEDENCE;
}
}
//Spring4.2后推荐使用这个代替上面的SmartApplicationListener
public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
boolean supportsEventType(ResolvableType eventType);
default boolean supportsSourceType(@Nullable Class<?> sourceType) {
return true;
}
@Override
default int getOrder() {
return LOWEST_PRECEDENCE;
}
}
广播器抽象
//该接口的实现类可以管理监听器列表,并且具有发送事件的能力。
//一个ApplicationEventMulticaster通常也是ApplicationContext。
public interface ApplicationEventMulticaster {
void addApplicationListener(ApplicationListener<?> listener);
void addApplicationListenerBean(String listenerBeanName);
void removeApplicationListener(ApplicationListener<?> listener);
void removeApplicationListenerBean(String listenerBeanName);
void removeAllListeners();
void multicastEvent(ApplicationEvent event);
void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}
//抽象实现,提供基本的注册、移除能力。multicastEvent方法由子类实现
AbstractApplicationEventMulticaster{
}
//广播器的真正实现。不管监听器是否感兴趣都会广播给它们。监听器自己可以过滤事件。
//默认是在当前线程调用所有监听器的方法。但是大量的监听器可能会阻塞整个应用,所以预留一个口子,可以传入一个TaskExecutor.
SimpleApplicationEventMulticaster{
}
最后看一下继承关系
上面也提到过,其实Spring
根据已有的事件类型,直接抽出对应的方法,然后直接调用方法发送即可,免却用户手动构造事件消息
public interface SpringApplicationRunListener {
//容器启动事件调用这个方法
void starting();
//环境准备好直接调这个
void environmentPrepared(ConfigurableEnvironment environment);
void contextPrepared(ConfigurableApplicationContext context);
//省略相关方法
}
//唯一实现类
EventPublishingRunListener {
private final SimpleApplicationEventMulticaster initialMulticaster;
@Override
public void starting() {
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
}
三、SpringBoot框架有哪些框架事件以及它们的顺序?
四、介绍下监听事件触发机制?
五、如何自定义实现系统监听器及注意事项?
实现方式一
- 实现
ApplicationListener
接口 spring.factories
内填写接口实现key
值为org.springframework.context.ApplicationListener
实现方式二
- 实现
ApplicationListener
接口 SpringApplication
类初始后调用addListeners
设置进去
实现方式三
- 实现
ApplicationListener
接口 application.properties
内填写接口实现key
值为context.listener.classes
实现方式四
- 实现
SmartApplicationListener
接口 - 重写
supportsEventType
方法 - 前三种注入方式注入框架均可
六、ApplicationListener接口与SmartApplicationListener接口辨析?
- 实现
ApplicationListener
接口针对单一事件监听 - 实现
SmartApplicationListener
接口针对多种事件监听 Order
值越小越先执行application.properties
中定义的优于其它方式