• springIOC源码接口分析(七):ApplicationEventPublisher


    一 定义方法

    此接口主要是封装事件发布功能的接口,定义了两个方法:

        /**
         * 通知应用所有已注册且匹配的监听器此ApplicationEvent
         */
        default void publishEvent(ApplicationEvent event) {
            publishEvent((Object) event);
        }
    
        /**
         * 通知应用所有已注册且匹配的监听器此Event ,
         * 如果这个Event不是一个ApplicationEvent,则其被包裹于PayloadApplicationEvent
         */
        void publishEvent(Object event);

    二 ApplicationEvent 事件抽象类

       spring中ApplicationEvent +ApplicationListener 是观察者模式的一种实现。

    public abstract class ApplicationEvent extends EventObject {
    
        /** use serialVersionUID from Spring 1.2 for interoperability. */
        private static final long serialVersionUID = 7099057708183571937L;
    
        /** 事件发生的系统时间 */
        private final long timestamp;
    
    
        // 构造器
        public ApplicationEvent(Object source) {//发生事件的对象
            super(source);
            this.timestamp = System.currentTimeMillis();
        }
    
        public final long getTimestamp() {
            return this.timestamp;
        }
    }
    ApplicationEvent类继承了EventObject类 ,构造器中的source都是父类的不需要序列化的属性,添加了自身的事件发生时间的属性

     transient作用: https://www.cnblogs.com/chenpi/p/6185773.html

    三 spring内置事件

     spring里面有许多Event的实现,包括springBoot里面又新增了一些实现,下面是这些实现:

     ApplicationEvent的实现主要分为三条线:

     1 PayloadApplicationEvent,是可以使用泛型的事件,不用进行强转

     2 ApplicationContextEvent以及其四个子类

        ApplicationContextEvent是对应应用上下文的事件,主要有四个事件,分别是:

    • ContextRefreshedEvent  刷新

    • ContextClosedEvent  关闭

    • ContextStartedEvent  启动

    • ContextStoppedEvent  暂停

     3 RequestHandledEvent,对应http服务事件,其实现类定义了一些http请求有关的参数,url,状态code等:

    三 ApplicationListener 监听器接口

    @FunctionalInterface
    public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
    
        /**
         * Handle an application event.
         * @param event the event to respond to
         */
        void onApplicationEvent(E event);
    
    }

    ApplicationListener接口继承了EventListener 接口,java中所有的监听器都继承了这个接口猛兽jdk,util包下面的接口,接口接受ApplicationEvent的子类作为监听事件.
    使用监听器一般有两种方式:

      一 实现ApplicationListener接口

       比如spring内置的一个监听器:

      

     二 使用@EventListener注解的方式

      

    注册了监听器之后,发布对应事件就会通过事件处理器管理类多播到对应的监听逻辑,即onApplicationEvent方法

    四 ApplicationEventMulticaster 事件处理器管理类

      ApplicationEventMulticaster接口定义了7个管理监听器的方法,只有一个实现类SimpleApplicationEventMulticaster,方法分别是:

      

        /**
         * 添加监听器,用来接收所有事件的通知
         */
        void addApplicationListener(ApplicationListener<?> listener);
    
        /**
         * 根据Bean名称添加监听器
         */
        void addApplicationListenerBean(String listenerBeanName);
    
        /**
         * 移除监听器
         */
        void removeApplicationListener(ApplicationListener<?> listener);
    
        /**
         * 根据名称移除监听器
         */
        void removeApplicationListenerBean(String listenerBeanName);
    
        /**
         * 移除所有监听器
         */
        void removeAllListeners();
    
        /**
         * 将事件广播到对应的监听器中
         */
        void multicastEvent(ApplicationEvent event);
    
        /**
         * 将事件广播到对应的监听器中
         */
        void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);

    接下来看实现类中广播事件的方法:

        @Override
        public void multicastEvent(ApplicationEvent event) {
            multicastEvent(event, resolveDefaultEventType(event));//获取默认类型
        }
    
        @Override
        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);//调用对应的监听器逻辑方法
                }
            }
        }

    类中维护了一个Set,用来存放监听器,且监听事件都是异步线程池执行的.

  • 相关阅读:
    oracle 日期和时间转换
    layui 分页 java后端封装
    excel 时间格式
    excel的编程VBA
    excel条件格式
    python列表变成字符串
    Django的ORM源码学习
    robot 源码解读6【元类和描述符类】
    @staticmethod
    python 类定义后调用名称也执行内部代码
  • 原文地址:https://www.cnblogs.com/houzheng/p/11885272.html
Copyright © 2020-2023  润新知