zoukankan      html  css  js  c++  java
  • 【Spring】事件监听实现原理(十)

    一、事件监听介绍

      原理: 观察者模式  

      spring的事件监听有三个部分组成:

    • 事件(ApplicationEvent) 负责对应相应监听器 事件源发生某事件是特定事件监听器被触发的原因。

    • 监听器(ApplicationListener) 对应于观察者模式中的观察者。监听器监听特定事件,并在内部定义了事件发生后的响应逻辑。

    • 事件发布器(ApplicationEventMulticaster )对应于观察者模式中的被观察者/主题, 负责通知观察者 对外提供发布事件和增删事件监听器的接口,维护事件和事件监听 器之间的映射关系,并在事件发生时负责通知相关监听器。

      

    二、事件监听使用

    1、事件

     1 public class MyApplicationEvent extends ApplicationEvent {
     2 
     3     private String msg;
     4 
     5     public MyApplicationEvent(Object source) {
     6         super(source);
     7     }
     8 
     9     public MyApplicationEvent(Object source, String msg) {
    10         super(source);
    11         this.msg = msg;
    12     }
    13 
    14     public String getMsg() {
    15         return msg;
    16     }
    17 
    18     public void setMsg(String msg) {
    19         this.msg = msg;
    20     }
    21 }

    2、监听器-接口模式

     1 @Component
     2 public class MyApplicationListener implements ApplicationListener {
     3     @Override
     4     public void onApplicationEvent(ApplicationEvent event) {
     5         System.out.println("MyApplicationListener: " +  "正在处理器事件");
     6         System.out.println("MyApplicationListener-事件源:" + event.getSource());
     7         if(event instanceof MyApplicationEvent) {
     8             System.out.println("MyApplicationListener-事件msg:" + ((MyApplicationEvent) event).getMsg());
     9         }
    10     }
    11 }

      监听器-注解模式

     1 @Component
     2 public class MyCustomListener {
     3 
     4     @EventListener
     5     public void processEvent(ApplicationEvent event){
     6         System.out.println("MyCustomListener: " +  "正在处理器事件");
     7         System.out.println("MyCustomListener-事件源:" + event.getSource());
     8         if(event instanceof MyApplicationEvent) {
     9             System.out.println("MyCustomListener-事件msg:" + ((MyApplicationEvent) event).getMsg());
    10         }
    11     }
    12 
    13 }
    View Code

    3、事件发布器,使用Spring内置的,配置类

    1 @Configuration
    2 @ComponentScan("com.test.listener.component")
    3 public class MainConfig {
    4     public MainConfig(){
    5         System.out.println("MainConfig 构造方法");
    6     }
    7 } 

     4、主方法启动

     1 public class MainStarter {
     2 
     3     public static void main(String[] args) {
     4         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
     5         // 1、创建一个事件
     6         MyApplicationEvent myApplicationEvent = new MyApplicationEvent(new Object(), "这是一个的新事件");
     7         // 2、发布事件
     8         context.publishEvent(myApplicationEvent);
     9         // 3、监听器处理
    10         // .....
    11         context.close();
    12     }
    13 
    14

     三、原理图

    1、事件监听相关类图

      

    2、执行流程图

      

    四、Spring事件监听源码分析

     1、在reflush(),方法中调用 initApplicationEventMulticaster() 初始化事件广播器

     1 protected void initApplicationEventMulticaster() {
     2     ConfigurableListableBeanFactory beanFactory = getBeanFactory();
     3     // 判断Bean工厂中是有没有applicationEventMulticaster 应用广播器组件
     4     if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
     5         // 直接显示的调用getBean获取出来赋值给的applicationContext对象
     6         this.applicationEventMulticaster =
     7                 beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
     8         if (logger.isTraceEnabled()) {
     9             logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
    10         }
    11     }
    12     // Bean工厂中没有的话
    13     else {
    14         // new 一个SimpleApplicationEventMulticaster对象
    15         this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
    16         // 并且注入到容器中
    17         beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
    18         if (logger.isTraceEnabled()) {
    19             logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
    20                     "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
    21         }
    22     }
    23 }

    2、在reflush(),方法中调用registerListeners() 注册监听器

     1 protected void registerListeners() {
     2     // Register statically specified listeners first.
     3     // 获取容器中所有的监听器对象(成品对象)
     4     for (ApplicationListener<?> listener : getApplicationListeners()) {
     5         // 把监听器的注册到事件广播器上去
     6         getApplicationEventMulticaster().addApplicationListener(listener);
     7     }
     8 
     9     // Do not initialize FactoryBeans here: We need to leave all regular beans
    10     // uninitialized to let post-processors apply to them!
    11     // 根据类型从bean工厂的bean定义中,获取bean定义名单
    12     String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
    13     for (String listenerBeanName : listenerBeanNames) {
    14         // 把监听器的注册到事件广播器上去,只是注册的名单
    15         getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
    16     }
    17 
    18     // Publish early application events now that we finally have a multicaster...
    19     // 获取早期事件
    20     Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
    21     this.earlyApplicationEvents = null;
    22     if (earlyEventsToProcess != null) {
    23         for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
    24             // 获取事件广播器,发布早期事件
    25             getApplicationEventMulticaster().multicastEvent(earlyEvent);
    26         }
    27     }
    28 } 

     3、发布事件方法  publishEvent()

     1 protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
     2     Assert.notNull(event, "Event must not be null");
     3 
     4     // Decorate event as an ApplicationEvent if necessary
     5     // 1、如有必要,将事件装饰为ApplicationEvent
     6     ApplicationEvent applicationEvent;
     7     if (event instanceof ApplicationEvent) {
     8         applicationEvent = (ApplicationEvent) event;
     9     }
    10     else {
    11         applicationEvent = new PayloadApplicationEvent<>(this, event);
    12         if (eventType == null) {
    13             eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
    14         }
    15     }
    16 
    17     // Multicast right now if possible - or lazily once the multicaster is initialized
    18     if (this.earlyApplicationEvents != null) {
    19         this.earlyApplicationEvents.add(applicationEvent);
    20     }
    21     else {
    22         //  2、使用事件广播器广播事件到相应的监听器
    23         getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
    24     }
    25 
    26     // Publish event via parent context as well...
    27     // 3、如果有父容器
    28     if (this.parent != null) {
    29         if (this.parent instanceof AbstractApplicationContext) {
    30             // 使用父容器,带事件类型参数的,    发布事件
    31             ((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
    32         }
    33         else {
    34             // 使用父容器发布事件
    35             this.parent.publishEvent(event);
    36         }
    37     }
    38 } 

     4、广播器广播事件方法 multicastEvent()

     1 @Override
     2 public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
     3     ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
     4     // 1、返回此广播器的当前任务执行器
     5     Executor executor = getTaskExecutor();
     6     // 2、、getApplicationListeners:返回与给定事件类型匹配的应用监听器集合
     7     for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
     8         // 3.1 executor不为null,则使用executor调用监听器
     9         if (executor != null) {
    10             executor.execute(() -> invokeListener(listener, event));
    11         }
    12         // 3.2 否则,直接调用监听器
    13         else {
    14             invokeListener(listener, event);
    15         }
    16     }
    17 } 

      5、广播器广播事件方法 multicastEvent() , 其中 doInvokeListener() 就去调用了监听器的处理事件方法

     1 protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
     2     // 1.返回此广播器的当前错误处理器
     3     ErrorHandler errorHandler = getErrorHandler();
     4     if (errorHandler != null) {
     5         try {
     6             // 2.1 如果errorHandler不为null,则使用带错误处理的方式调用给定的监听器
     7             doInvokeListener(listener, event);
     8         }
     9         catch (Throwable err) {
    10             errorHandler.handleError(err);
    11         }
    12     }
    13     else {
    14         // 2.2 否则,直接调用调用给定的监听器
    15         doInvokeListener(listener, event);
    16     }
    17 }
  • 相关阅读:
    Python 基础(二)
    Python 入门
    DNS
    PXE自动化安装CentOS7和CentOS6
    AIDE及sudo应用
    SSH应用
    KickStart自动化安装Linux
    初见鸟哥
    数组ARRAY
    SSH用法
  • 原文地址:https://www.cnblogs.com/h--d/p/14660662.html
Copyright © 2011-2022 走看看