• 发布订阅(观察者)模式之Spring源码ApplicationListener解析


    发布订阅模式之Spring源码ApplicationListener解析

    • 在之前的博客中有介绍过发布订阅模式, 也就是观察者模式, 想要了解的同学可以看我博客https://editor.csdn.net/md/?articleId=126689739

    • 他的uml图如下(图一)

    • 在这里插入图片描述

    • 这里我们在重点讲一下发布订阅模式在spring源码中的应用

    • 为了大家有一个整体的认识, 我先把主要涉及到的类先画出uml, 如下

    • 在这里插入图片描述

    • 接下来我们来分析一下源码

    • ApplicationListener作为观察者, 定义onApplicationEvent。 对应图一的Observer

      •   public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
          
          	/**
          	 * Handle an application event.
          	 * @param event the event to respond to
          	 */
          	void onApplicationEvent(E event);
          
          }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
    • 事件的发布, 是通过ApplicationContext 的publishEvent , 他的默认实现是接口ApplicationEventPublisher, 所以 ApplicationContext 就作为观察目标(图一的Subject)

      •   public interface ApplicationEventPublisher {
          
          	/**
          	 * Notify all matching listeners registered with this
          	 * application of an application event. Events may be framework events
          	 * (such as RequestHandledEvent) or application-specific events.
          	 * @param event the event to publish
          	 * @see org.springframework.web.context.support.RequestHandledEvent
          	 */
          	default void publishEvent(ApplicationEvent event) {
          		publishEvent((Object) event);
          	}
          
          	/**
          	 * Notify all matching listeners registered with this
          	 * application of an event.
          	 * 

        If the specified {@code event} is not an {@link ApplicationEvent}, * it is wrapped in a {@link PayloadApplicationEvent}. * @param event the event to publish * @since 4.2 * @see PayloadApplicationEvent */ void publishEvent(Object event); }

        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
    • 我们再看一下实现细节, 可以找到AbstractApplicationContext, 代码片段如下

      •   	protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
          		Assert.notNull(event, "Event must not be null");
          		if (logger.isTraceEnabled()) {
          			logger.trace("Publishing event in " + getDisplayName() + ": " + event);
          		}
          
          		// Decorate event as an ApplicationEvent if necessary
          		ApplicationEvent applicationEvent;
          		if (event instanceof ApplicationEvent) {
          			applicationEvent = (ApplicationEvent) event;
          		}
          		else {
          			applicationEvent = new PayloadApplicationEvent<>(this, event);
          			if (eventType == null) {
          				eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
          			}
          		}
          
          		// Multicast right now if possible - or lazily once the multicaster is initialized
          		if (this.earlyApplicationEvents != null) {
          			this.earlyApplicationEvents.add(applicationEvent);
          		}
          		else {
          			getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
          		}
          
          		// Publish event via parent context as well...
          		if (this.parent != null) {
          			if (this.parent instanceof AbstractApplicationContext) {
          				((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
          			}
          			else {
          				this.parent.publishEvent(event);
          			}
          		}
          	}
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
      • 重点看 getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);这是他的具体实现, 可以定位到org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent, 代码如下, 也是用for循环去便利观察者, 参考图一中的for

        •   	public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
            		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
            		for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
            			Executor executor = getTaskExecutor();
            			if (executor != null) {
            				executor.execute(() -> invokeListener(listener, event));
            			}
            			else {
            				invokeListener(listener, event);
            			}
            		}
            	}
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
        • 最后我们看一下invokeListener的实现, doInvokeListener, 可以发现, 是调用了观察者ApplicationListener的onApplicationEvent方法

          •   	private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
              		try {
              			listener.onApplicationEvent(event);
              		}
              		catch (ClassCastException ex) {
              			String msg = ex.getMessage();
              			if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
              				// Possibly a lambda-defined listener which we could not resolve the generic event type for
              				// -> let's suppress the exception and just log a debug message.
              				Log logger = LogFactory.getLog(getClass());
              				if (logger.isDebugEnabled()) {
              					logger.debug("Non-matching event type for listener: " + listener, ex);
              				}
              			}
              			else {
              				throw ex;
              			}
              		}
              	}
            
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            • 10
            • 11
            • 12
            • 13
            • 14
            • 15
            • 16
            • 17
            • 18
            • 19
      • 到这里你是不是已近明白了尼

  • 相关阅读:
    C++ ,VCPKG那些事
    Flexbox设计H5应用网页布局
    [Linux]基础IO上(C文件操作 | 系统文件IO | 文件描述符fd | 缓冲区概念)
    通讯网关软件007——利用CommGate X2Mbt实现Modbus TCP访问MSSQL服务器
    打包工具webpack的学习
    计算机毕业设计ssm软件项目Bug管理系统612ed系统+程序+源码+lw+远程部署
    word 多级目录的问题
    springboot+redis
    Spring学习笔记13 Spring对事务的支持
    R语言dplyr包mutate_if函数为dataframe数据中的所有数值列乘以某一固定数值并生成新的数据列(变量)
  • 原文地址:https://blog.csdn.net/biubiubiubibibi/article/details/126690023