zoukankan      html  css  js  c++  java
  • spring之自定义事件及监听 原理

    上一节说了自定义事件及监听的实现,这一节说下他的实现原理。

    首先他发布事件使用过ApplicationContext.publishEvent()方法来实现,通过追踪发现publishEvent()方法的实现是在AbstractApplicationContext抽象类中实现。

    先捋请这几个类的具体继承和接口实现的层级关系。

    eclipse下的:

     

    然后再看AbstractApplicationContext下的publishEvent方法:

     1     /**
     2      * Publish the given event to all listeners.
     3      * @param event the event to publish (may be an {@link ApplicationEvent}
     4      * or a payload object to be turned into a {@link PayloadApplicationEvent})
     5      * @param eventType the resolved event type, if known
     6      * @since 4.2
     7      */
     8     protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
     9         Assert.notNull(event, "Event must not be null");
    10 
    11         // Decorate event as an ApplicationEvent if necessary
    12         ApplicationEvent applicationEvent;
    13         if (event instanceof ApplicationEvent) {
    14             applicationEvent = (ApplicationEvent) event;
    15         }
    16         else {
    17             applicationEvent = new PayloadApplicationEvent<>(this, event);
    18             if (eventType == null) {
    19                 eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
    20             }
    21         }
    22 
    23         // Multicast right now if possible - or lazily once the multicaster is initialized
    24         if (this.earlyApplicationEvents != null) {
    25             this.earlyApplicationEvents.add(applicationEvent);
    26         }
    27         else {
    // SimpleApplicationEventMulticaster 获取事件发布器,发布事件
    28 getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType); 29 } 30 31 // Publish event via parent context as well... 32 if (this.parent != null) { 33 if (this.parent instanceof AbstractApplicationContext) { 34 ((AbstractApplicationContext) this.parent).publishEvent(event, eventType); 35 } 36 else { 37 this.parent.publishEvent(event); 38 } 39 } 40 }
    getApplicationEventMulticaster()代码:
     1 /**
     2      * Return the internal ApplicationEventMulticaster used by the context.
     3      * @return the internal ApplicationEventMulticaster (never {@code null})
     4      * @throws IllegalStateException if the context has not been initialized yet
     5      */
     6     ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
     7         if (this.applicationEventMulticaster == null) {
     8             throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
     9                     "call 'refresh' before multicasting events via the context: " + this);
    10         }
    11         return this.applicationEventMulticaster;
    12     }
    ApplicationEventMulticaster 的multicastEvent()方法是在SimpleApplicationEventMulticaster类中实现。下面是层级结构图。

    SimpleApplicationEventMulticaster.multicastEvent()代码
     1     @Override
     2     public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
     3         ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
    // getApplicationListeners(event, type) 筛选监听器,在context.publish(ApplicationEvent event)中已经将事件传入,getApplicationListeners中将可以根据这个event类型从Spring容器中检索出符合条件的监听器
    4 Executor executor = getTaskExecutor(); 5 for (ApplicationListener<?> listener : getApplicationListeners(event, type)) { 6 if (executor != null) { 7 executor.execute(() -> invokeListener(listener, event)); 8 } 9 else {
    10 invokeListener(listener, event);//尝试逐个向监听器广播 11 } 12 } 13 }

    下面是进行debug的结果:

          

    在multicastEvent发布完,就直接循环event事件
  • 相关阅读:
    使用性能监视器找出SQLServer硬件瓶颈
    重启sql server 服务
    优化SQL Server数据库查询方法
    tempdb对SQL Server数据库性能有何影响
    利用动态管理视图提高SQL Server索引效率
    SQL Server 2008 R2数据库镜像部署
    优化数据库的注意事项
    查看 SQL Server 2000 中数据表所占用的磁盘空间
    SQL Server 2005 排查I/O瓶颈
    SQL语句优化的原则
  • 原文地址:https://www.cnblogs.com/swfzzz/p/12036239.html
Copyright © 2011-2022 走看看