首页 > 编程语言 >Spring-事件监听 源码解析

Spring-事件监听 源码解析

时间:2023-03-15 18:35:31浏览次数:39  
标签:Spring void event listener public 源码 事件 监听器 监听

当我们的系统运行在一定的关键节点的时候,它会通过广播器发布一些事件出去;而我们系统中存在着部分监听器,它对某些关键节点的事件是感兴趣的,所以它会去订阅这部分消息;当这些事件被发布出去之后,它们就会监听到这些事件,从而去触发一些行为。  

一、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

相关文章