• PDS-SpringBoot监听器


    一、介绍下监听器模式?

    image-20200713220545194

    核心组件:广播器、事件、监听器

    所谓监听就是事件发生时,通过广播器持有的监听器列表,循环调用监听器的方法

    事件源

    #抽象事件
    public abstract class WeatherEvent {
        public abstract String getWeather();
    }
    public class RainEvent extends WeatherEvent {
        @Override
        public String getWeather() {
            return "rain";
        }
    }
    public class SnowEvent extends WeatherEvent {
        @Override
        public String getWeather() {
            return "snow";
        }
    }

    监听器

    #抽象监听器
    public interface WeatherListener {
        void onWeatherEvent(WeatherEvent event);
    }
    
    
    public class RainListener implements WeatherListener {
        @Override
        public void onWeatherEvent(WeatherEvent event) {
            if (event instanceof RainEvent) {
                System.out.println("hello " + event.getWeather());
            }
        }
    }
    
    
    public class SnowListener implements WeatherListener {
        @Override
        public void onWeatherEvent(WeatherEvent event) {
            if (event instanceof SnowEvent) {
                System.out.println("hello " + event.getWeather());
            }
        }
    }

    广播器

    #事件广播器
    public interface EventMulticaster {
        //核心能力,发送事件
        void multicastEvent(WeatherEvent event);
        //注册和移除监听器
        void addListener(WeatherListener weatherListener);
        void removeListener(WeatherListener weatherListener);
    }
    
    
    public abstract class AbstractEventMulticaster implements EventMulticaster {
        //@Autowired,map/list 借助Spring得能力也可以注入
        private List<WeatherListener> listenerList;
    
    
        @Override
        public void multicastEvent(WeatherEvent event) {
            doStart();
            listenerList.forEach(i -> i.onWeatherEvent(event));
            doEnd();
        }
    
    
        @Override
        public void addListener(WeatherListener weatherListener) {
            listenerList.add(weatherListener);
        }
    
    
        @Override
        public void removeListener(WeatherListener weatherListener) {
            listenerList.remove(weatherListener);
        }
        //钩子方法,由子类实现
        abstract void doStart();
        abstract void doEnd();
    }
    #子类
    public class WeatherEventMulticaster extends AbstractEventMulticaster {
    
    
        @Override
        void doStart() {
            System.out.println("begin broadcast weather event");
        }
    
    
        @Override
        void doEnd() {
            System.out.println("end broadcast weather event");
        }
    }

    可以看到,如果实际代码中要发送事件,必须持有一个EventMulticaster的实现,然后调用相应的方法。这样做稍显麻烦,从Spring的代码中可以学到一招。

    @Component
    public class WeatherRunListener {
        @Autowired
        private WeatherEventMulticaster eventMulticaster;
    
    
        public void snow() {
            eventMulticaster.multicastEvent(new SnowEvent());
        }
        public void rain() {
            eventMulticaster.multicastEvent(new RainEvent());
        }
    }

    这样,我们只需要持有WeatherRunListener即可,想发送什么事件可以掉对应的方法。

    掌握监听器的核心还是在于把握三要素。

    二、SpringBoot关于监听器相关的实现类有哪些?

    事件抽象及子类

    public abstract class ApplicationEvent extends EventObject {
        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;
        }
    }

    image-20200713221831734

    监听器抽象

    #可以通过泛型指定自己感兴趣的类型
    @FunctionalInterface
    public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
        void onApplicationEvent(E event);
    }
    
    
    //看到下面的support方法,应该可以猜到这个是通过support方法来表明自己对哪些时间感兴趣
    public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
    
    
        /**
         * Determine whether this listener actually supports the given event type.
         * @param eventType the event type (never {@code null})
         */
        boolean supportsEventType(Class<? extends ApplicationEvent> eventType);
    
    
        /**
         * Determine whether this listener actually supports the given source type.
         * <p>The default implementation always returns {@code true}.
         * @param sourceType the source type, or {@code null} if no source
         */
        default boolean supportsSourceType(@Nullable Class<?> sourceType) {
            return true;
        }
        @Override
        default int getOrder() {
            return LOWEST_PRECEDENCE;
        }
    }
    
    
    //Spring4.2后推荐使用这个代替上面的SmartApplicationListener
    public interface GenericApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
        boolean supportsEventType(ResolvableType eventType);
        default boolean supportsSourceType(@Nullable Class<?> sourceType) {
            return true;
        }
        @Override
        default int getOrder() {
            return LOWEST_PRECEDENCE;
        }
    } 

    广播器抽象

    //该接口的实现类可以管理监听器列表,并且具有发送事件的能力。
    //一个ApplicationEventMulticaster通常也是ApplicationContext。
    public interface ApplicationEventMulticaster {
        void addApplicationListener(ApplicationListener<?> listener);
        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);
    }
    //抽象实现,提供基本的注册、移除能力。multicastEvent方法由子类实现
    AbstractApplicationEventMulticaster{
    }
    //广播器的真正实现。不管监听器是否感兴趣都会广播给它们。监听器自己可以过滤事件。
    //默认是在当前线程调用所有监听器的方法。但是大量的监听器可能会阻塞整个应用,所以预留一个口子,可以传入一个TaskExecutor.
    SimpleApplicationEventMulticaster{
    }

    最后看一下继承关系

    上面也提到过,其实Spring根据已有的事件类型,直接抽出对应的方法,然后直接调用方法发送即可,免却用户手动构造事件消息

    public interface SpringApplicationRunListener {
        //容器启动事件调用这个方法
        void starting();
        //环境准备好直接调这个
        void environmentPrepared(ConfigurableEnvironment environment);
        void contextPrepared(ConfigurableApplicationContext context);
        //省略相关方法
    }
    
    
    //唯一实现类
    EventPublishingRunListener {
        private final SimpleApplicationEventMulticaster initialMulticaster;
    
        @Override
        public void starting() {
            this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
        }
    }

    三、SpringBoot框架有哪些框架事件以及它们的顺序?

    image-20200713221831734

    image-20200713222050519

    四、介绍下监听事件触发机制?

    image-20200713224456297

    五、如何自定义实现系统监听器及注意事项?

    实现方式一

    1. 实现ApplicationListener接口
    2. spring.factories内填写接口实现
    3. key值为org.springframework.context.ApplicationListener

    实现方式二

    1. 实现ApplicationListener接口
    2. SpringApplication类初始后调用addListeners设置进去

    实现方式三

    1. 实现ApplicationListener接口
    2. application.properties内填写接口实现
    3. key值为context.listener.classes

    实现方式四

    1. 实现SmartApplicationListener接口
    2. 重写supportsEventType方法
    3. 前三种注入方式注入框架均可

    image-20200713222229203

    六、ApplicationListener接口与SmartApplicationListener接口辨析?

    • 实现ApplicationListener接口针对单一事件监听
    • 实现SmartApplicationListener接口针对多种事件监听
    • Order值越小越先执行
    • application.properties中定义的优于其它方式

    七、监听器查找过程

    image-20200713224401339





    网络知识搬运/梳理小工
  • 相关阅读:
    算法(第四版)C# 习题题解——2.4
    算法(第四版)C# 习题题解——2.3
    .NET编译的目标平台(AnyCPU,x86,x64)
    Windows无法访问局域网内共享文件夹[0x800704cf,0x80070035]解决方案
    ASP.NET 网站部署到IIS上如何进行调试
    ASP.NET 前台Javascript调用后台代码 / 后台调用前台Javascript
    C#反射-Assembly.Load、LoadFrom与LoadFile
    Entity Framework Context上下文管理(CallContext 数据槽)
    Entity Framework(EF的Code First方法)
    Entity Framework(EF的Model First方法)
  • 原文地址:https://www.cnblogs.com/aibilim/p/641992700e419aca11803a4391a0d1de.html
Copyright © 2020-2023  润新知