当我们的系统运行在一定的关键节点的时候,它会通过广播器发布一些事件出去;而我们系统中存在着部分监听器,它对某些关键节点的事件是感兴趣的,所以它会去订阅这部分消息;当这些事件被发布出去之后,它们就会监听到这些事件,从而去触发一些行为。
一、Spring 中的监听器实现
1. 组件一: 事件
Spring中最顶层的是EventObject类,表示一个事件对象;抽象类ApplicationEvent继承自EventObject类,表示一个应用事件。
- EventObject:
1 public class EventObject implements Serializable { 2 private static final long serialVersionUID = 5516075349620653480L; 3 protected transient Object source; 4 5 public EventObject(Object var1) { 6 if (var1 == null) { 7 throw new IllegalArgumentException("null source"); 8 } else { 9 this.source = var1; 10 } 11 } 12 13 public Object getSource() { 14 return this.source; 15 } 16 17 public String toString() { 18 return this.getClass().getName() + "[source=" + this.source + "]"; 19 } 20 }
- ApplicationEvent:
1 public abstract class ApplicationEvent extends EventObject { 2 3 /** use serialVersionUID from Spring 1.2 for interoperability. */ 4 private static final long serialVersionUID = 7099057708183571937L; 5 6 /** System time when the event happened. */ 7 private final long timestamp; 8 9 10 /** 11 * Create a new {@code ApplicationEvent}. 12 * @param source the object on which the event initially occurred or with 13 * which the event is associated (never {@code null}) 14 */ 15 public ApplicationEvent(Object source) { 16 super(source); 17 this.timestamp = System.currentTimeMillis(); 18 } 19 20 21 /** 22 * Return the system time in milliseconds when the event occurred. 23 */ 24 public final long getTimestamp() { 25 return this.timestamp; 26 } 27 28 }
如果模拟Spring自实现监听器:
① 首先定义一个事件 抽象类 Event,那么其他要被监控的事件均要继承它:
1 /** 2 * 事件 3 * 4 * @author yangyongjie 5 * @date 2020/9/30 6 */ 7 public abstract class Event<T> { 8 /** 9 * 事件自身资源,用来发布任务时传递一些参数信息 10 */ 11 protected T source; 12 /** 13 * 事件发生时间 14 */ 15 private final long timestamp; 16 17 protected Event(T source) { 18 this.source = source; 19 this.timestamp = System.currentTimeMillis(); 20 } 21 22 public T getSource() { 23 return source; 24 } 25 26 public void setSource(T source) { 27 this.source = source; 28 } 29 30 public long getTimestamp() { 31 return timestamp; 32 } 33 }
比如在实际使用时:对节目进行发布,需要单独写个事件去继承Event:
1 public class PublishMovieEvent extends Event<Long[]> { 2 public PublishMovieEvent(Long[] source) { 3 super(source); 4 } 5 }
2. 组件二:监听器
ApplicationListener继承自EventListener,EventListener 是一个空接口,用来声明这是一个事件监听的接口。
- EventListener:
1 public interface EventListener { 2 }
- ApplicationListener:其泛型继承自ApplicationEvent,因此在实现这个接口的时候,可以声明自己监听的具体事件。系统在触发这个系统监听器的时候会根据其监听的事件做一个过滤。
1 @FunctionalInterface 2 public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { 3 4 /** 5 * Handle an application event. 6 * @param event the event to respond to 7 */ 8 void onApplicationEvent(E event); // 监听到事件发生的时候,去做一些事情 9 10 }
如果模拟Spring自实现监听器:
② 定义一个监听器接口 Listener,那么其他自定义的监听器均要实现它;其中泛型E表示要监听的事件
1 /** 2 * 监听器 3 * 4 * @author yangyongjie 5 * @date 2020/9/30 6 * @desc 7 */ 8 public interface Listener<E extends Event> { 9 10 /** 11 * 当事件发生时做一些事情 12 * 13 * @param event 14 */ 15 void onEvent(E event); 16 }
比如在实际使用时:对节目进行发布,需要单独定义个监听器去实现Listener接口:
1 @Component 2 public class PublishMovieListener implements Listener<PublishMovieEvent> { 3 4 private static final Logger LOGGER = LoggerFactory.getLogger(PublishMovieListener.class); 5 6 @Resource 7 private MovieService movieService; 8 9 @Override 10 public void onEvent(PublishMovieEvent event) { 11 movieService.publish(Arrays.asList(event.getSource())); 12 String metaIds = JsonUtil.toString(event.getSource()); 13 LOGGER.info("发布节目成功: meta_id = {}", metaIds); 14 } 15 }
3. 组件三:广播器
广播器是 ApplicationEventMulticaster,有两个作用:
一是将事件监听器注册到广播器中:这样广播器就知道了每个事件监听器分别监听什么事件,且知道了每个事件对应哪些事件监听器在监听;
二是将事件广播给事件监听器:当有事件发生时,需要通过广播器来广播给所有的事件监听器。
ApplicationEventMulticaster中定义了添加、移除监听器以及广播事件的方法。
- ApplicationEventMulticaster:
1 public interface ApplicationEventMulticaster { 2 3 /** 4 * Add a listener to be notified of all events. 5 * @param listener the listener to add 6 */ 7 void addApplicationListener(ApplicationListener<?> listener); 8 9 /** 10 * Add a listener bean to be notified of all events. 11 * @param listenerBeanName the name of the listener bean to add 12 */ 13 void addApplicationListenerBean(String listenerBeanName); 14 15 /** 16 * Remove a listener from the notification list. 17 * @param listener the listener to remove 18 */ 19 void removeApplicationListener(ApplicationListener<?> listener); 20 21 /** 22 * Remove a listener bean from the notification list. 23 * @param listenerBeanName the name of the listener bean to remove 24 */ 25 void removeApplicationListenerBean(String listenerBeanName); 26 27 /** 28 * Remove all listeners registered with this multicaster. 29 * <p>After a remove call, the multicaster will perform no action 30 * on event notification until new listeners are registered. 31 */ 32 void removeAllListeners(); 33 34 /** 35 * Multicast the given application event to appropriate listeners. 36 * <p>Consider using {@link #multicastEvent(ApplicationEvent, ResolvableType)} 37 * if possible as it provides better support for generics-based events. 38 * @param event the event to multicast 39 */ 40 void multicastEvent(ApplicationEvent event); 41 42 /** 43 * Multicast the given application event to appropriate listeners. 44 * <p>If the {@code eventType} is {@code null}, a default type is built 45 * based on the {@code event} instance. 46 * @param event the event to multicast 47 * @param eventType the type of event (can be {@code null}) 48 * @since 4.2 49 */ 50 void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType); 51 52 }
如何注册所有的事件监听器呢?可参考:
- AbstractApplicationContext:
1 /** 注册事件监听器*/ 2 protected void registerListeners() { 3 //1.遍历将通过编码方式创建的事件监听器加入到事件广播器中 4 for (ApplicationListener<?> listener : getApplicationListeners()) { 5 //2.获取到当前事件广播器,添加事件监听器 6 getApplicationEventMulticaster().addApplicationListener(listener); 7 } 8 9 //3.从BeanFactory中获取所有实现了ApplicationListener接口的bean,遍历加入到事件广播器中 10 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); 11 for (String listenerBeanName : listenerBeanNames) { 12 getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); 13 } 14 15 //3.获取需要提前发布的事件 16 Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; 17 this.earlyApplicationEvents = null; 18 if (earlyEventsToProcess != null) { 19 for (ApplicationEvent earlyEvent : earlyEventsToProcess) { 20 //5.遍历将提前发布的事件广播出去 21 getApplicationEventMulticaster().multicastEvent(earlyEvent); 22 } 23 }
如何获取指定事件监听的监听器呢?可参考:
- GenericApplicationListenerAdapter
大致就是判断监听器的泛型的类型,是否与发布事件的类型一致,如果一致将监听器的对象放到一个集合中。
其中的resolveDeclaredEventType是Spring内部实现的一个泛型解析器,会根据类定义获得该类声明的事件类型。
1 @Nullable 2 private static ResolvableType resolveDeclaredEventType(ApplicationListener<ApplicationEvent> listener) { 3 ResolvableType declaredEventType = resolveDeclaredEventType(listener.getClass()); 4 // 如果listener被aop代理,则获取到的declaredEventType为null,isAssignableFrom:判断参数类型是否与当前类型相同或是当前类型的子类 5 if (declaredEventType == null || declaredEventType.isAssignableFrom(ApplicationEvent.class)) { 6 // 获取被aop代理的目标类(被代理listener) 7 Class<?> targetClass = AopUtils.getTargetClass(listener); 8 if (targetClass != listener.getClass()) { 9 // 解析listener监听的事件类型 10 declaredEventType = resolveDeclaredEventType(targetClass); 11 } 12 } 13 return declaredEventType; 14 } 15 16 @Nullable 17 static ResolvableType resolveDeclaredEventType(Class<?> listenerType) { 18 ResolvableType eventType = eventTypeCache.get(listenerType); 19 if (eventType == null) { 20 // 获取泛型类型 21 eventType = ResolvableType.forClass(listenerType).as(ApplicationListener.class).getGeneric(); 22 eventTypeCache.put(listenerType, eventType); 23 } 24 return (eventType != ResolvableType.NONE ? eventType : null); 25 }
如果模拟Spring自实现监听器:
③ 广播器(事件发布器):管理监听器,发布事件
1)广播器接口:
1 /** 2 * 事件广播器 3 * 4 * @author yangyongjie 5 * @date 2020/9/30 6 */ 7 public interface EventMulticaster { 8 9 /** 10 * 添加监听器 11 * 12 * @param listener 13 */ 14 void addListener(Listener<?> listener); 15 16 /** 17 * 移除监听器 18 * 19 * @param listener 20 */ 21 void removeListener(Listener<?> listener); 22 23 /** 24 * 发布事件,默认异步执行监听 25 * 26 * @param event 27 */ 28 void multicastEvent(Event<?> event); 29 30 /** 31 * 发布事件,按参数确定异步还是同步执行监听 32 * 33 * @param event 34 * @param async 35 */ 36 void multicastEvent(Event<?> event, boolean async); 37 38 /** 39 * 发布事件 40 * 41 * @param event 事件实例 42 * @param async 是否异步 43 * @param delayMillis 延迟毫秒数 44 */ 45 void multicastEvent(Event<?> event, boolean async, long delayMillis); 46 47 }
2)广播器实现类:
1 import org.slf4j.Logger; 2 import org.slf4j.LoggerFactory; 3 import org.springframework.aop.support.AopUtils; 4 import org.springframework.beans.BeansException; 5 import org.springframework.context.ApplicationContext; 6 import org.springframework.context.ApplicationContextAware; 7 import org.springframework.core.ResolvableType; 8 import org.springframework.stereotype.Component; 9 10 import java.util.LinkedHashSet; 11 import java.util.Map; 12 import java.util.Set; 13 14 /** 15 * 广播器(事件发布器) 16 * 17 * @author yangyongjie 18 * @date 2020/10/15 19 */ 20 @Component 21 public class SimpleEventMulticaster implements EventMulticaster, ApplicationContextAware { 22 23 private static final Logger LOGGER = LoggerFactory.getLogger(SimpleEventMulticaster.class); 24 25 private final Set<Listener<?>> listeners = new LinkedHashSet<>(); 26 27 @Override 28 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 29 // 获取容器中实现Listener接口的监听器,并添加到listeners缓存中 30 Map<String, Listener> listenerMap = applicationContext.getBeansOfType(Listener.class); 31 for (Map.Entry<String, Listener> entry : listenerMap.entrySet()) { 32 addListener(entry.getValue()); 33 } 34 // 为EventCaster设置SimpleEventMulticaster的实例 35 EventCaster.SetSimpleEventMulticaster(this); 36 } 37 38 @Override 39 public void addListener(Listener<?> listener) { 40 this.listeners.add(listener); 41 } 42 43 @Override 44 public void removeListener(Listener<?> listener) { 45 this.listeners.remove(listener); 46 } 47 48 @Override 49 public void multicastEvent(Event<?> event) { 50 multicastEvent(event, true); 51 } 52 53 @Override 54 public void multicastEvent(Event<?> event, boolean async) { 55 multicastEvent(event, async, 0L); 56 } 57 58 @Override 59 public void multicastEvent(Event<?> event, boolean async, long delayMillis) { 60 // 如果延迟时间不为0,则睡眠等待 61 if (delayMillis != 0) { 62 try { 63 Thread.sleep(delayMillis); 64 } catch (InterruptedException e) { 65 LOGGER.error(e.getMessage(), e); 66 } 67 } 68 Class<?> eventClass = event.getClass(); 69 Set<Listener<?>> interestedListeners = getInterestedListeners(eventClass); 70 // 事件发生,异步调用监听器的事件方法 71 for (Listener<?> listener : interestedListeners) { 72 if (async) { 73 ThreadPoolUtil.execute(() -> invokeListener(listener, event)); 74 } else { 75 invokeListener(listener, event); 76 } 77 } 78 } 79 80 /** 81 * 调用监听器执行 82 * 83 * @param listener 84 * @param event 85 */ 86 private void invokeListener(Listener listener, Event<?> event) { 87 try { 88 listener.onEvent(event); 89 } catch (Exception e) { 90 LOGGER.error(e.getMessage(), e); 91 } 92 } 93 94 /** 95 * 获取对当前事件感兴趣的监听器(监听了当前事件或当前事件的父事件) 96 * 97 * @param eventClass 98 */ 99 private Set<Listener<?>> getInterestedListeners(Class<?> eventClass) { 100 // 存放监听对发布事件感兴趣的监听器 101 Set<Listener<?>> interestedListeners = new LinkedHashSet<>(); 102 for (Listener<?> listener : listeners) { 103 // 避免listener被aop代理,因此获取其被代理的listener 104 Class<?> targetClass = AopUtils.getTargetClass(listener); 105 // 获取监听器的泛型类型(即监听器监听的事件类型) 106 ResolvableType genericEventType = ResolvableType.forClass(targetClass).as(Listener.class).getGeneric(); 107 // 监听器监听的事件类型是否是发布事件类型的父类 或与发布的事件类型相同 108 boolean interested = genericEventType.isAssignableFrom(eventClass); 109 if (interested) { 110 interestedListeners.add(listener); 111 } 112 } 113 return interestedListeners; 114 } 115 116 }
3)写一个工具类EventCaster:
1 /** 2 * 事件发布器 3 * 4 * @author yangyongjie 5 */ 6 public class EventCaster { 7 8 private static SimpleEventMulticaster simpleEventMulticaster; 9 10 public static void SetSimpleEventMulticaster(SimpleEventMulticaster simpleEventMulticaster) { 11 EventCaster.simpleEventMulticaster = simpleEventMulticaster; 12 } 13 14 /** 15 * 异步的事件发布 16 * 17 * @param event 18 */ 19 public static void multicastEvent(Event<?> event) { 20 simpleEventMulticaster.multicastEvent(event); 21 } 22 23 /** 24 * 自定义同步or异步的事件发布 25 * 26 * @param event 27 * @param async 28 */ 29 public static void multicastEvent(Event<?> event, boolean async) { 30 simpleEventMulticaster.multicastEvent(event, async); 31 } 32 33 /** 34 * 支持事件延迟发布 35 * 36 * @param event 37 * @param async 38 * @param delayMillis 39 */ 40 public static void multicastEvent(Event<?> event, boolean async, long delayMillis) { 41 simpleEventMulticaster.multicastEvent(event, async, delayMillis); 42 } 43 44 }
比如在实际使用时:对节目进行发布,直接写下面这行代码即可,将发布时机穿插在业务方法执行过程中
1 EventCaster.multicastEvent(new PublishMovieEvent(new Long[]{movie.getId()}));
end.
标签:Spring,void,event,listener,public,源码,事件,监听器,监听 From: https://www.cnblogs.com/zhulei1123/p/17219546.html