【1、spring事件】相关

一、【spring事件】相关

1.观察者模式【行为型模式】

  • 1.1、定义

    • 又被称为发布-订阅(Publish/Subscribe)模式,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
  • 1.2结构

    在观察者模式中有如下角色:

    • Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
    • ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
    • Observer:抽象观察者,是观察者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
    • ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
  • 1.3、优缺点

    1,优点:

    • 降低了目标与观察者之间的耦合关系,两者之间是抽象耦合关系。
    • 被观察者发送通知,所有注册的观察者都会收到信息【可以实现广播机制】

    2,缺点:

    • 如果观察者非常多的话,那么所有的观察者收到被观察者发送的通知会耗时
    • 如果被观察者有循环依赖的话,那么被观察者发送通知会使观察者循环调用,会导致系统崩溃
  • 1.4、使用场景

    • 对象间存在一对多关系,一个对象的状态发生改变会影响其他对象。
    • 当一个抽象模型有两个方面,其中一个方面依赖于另一方面时。

2、适配器模式(结构型模式)

  • 2.1、定义
    • 将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
  • 2.2、结构
    • 目标(Target)接口:当前系统业务所期待的接口,它可以是抽象类或接口。
    • 适配者(Adaptee)类:它是被访问和适配的现存组件库中的组件接口。
    • 适配器(Adapter)类:它是一个转换器,通过继承或引用适配者的对象,把适配者接口转换成目标接口,让客户按目标接口的格式访问适配者。

ctrl+shift+alt+n:全局查找器查找所有的类

3、spring事件

3.1、事件监听的3种方式

  • 1、实现 ApplicationListener 接口

    • 根据接口泛型确定事件类型

    相关代码

    // 事件解耦例子
    @Configuration
    public class A48_1 {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_1.class);
            context.getBean(MyService.class).doBusiness();
            context.close();
        }
    
        static class MyEvent extends ApplicationEvent {
            public MyEvent(Object source) {
                super(source);
            }
        }
        @Component
        static class MyService {
            private static final Logger log = LoggerFactory.getLogger(MyService.class);
            @Autowired
            private ApplicationEventPublisher publisher; // applicationContext 具体主题角色类
            public void doBusiness() {
                log.debug("主线业务");
                // 主线业务完成后需要做一些支线业务,下面是问题代码
                publisher.publishEvent(new MyEvent("MyService.doBusiness()"));
            }
        }
    
        //具体主题角色类
        @Component
        static class SmsApplicationListener implements ApplicationListener<MyEvent> {
            private static final Logger log = LoggerFactory.getLogger(SmsApplicationListener.class);
            @Override
            public void onApplicationEvent(MyEvent event) {
                log.debug("发送短信");
            }
        }
    
        @Component
        static class EmailApplicationListener implements ApplicationListener<MyEvent> {
            private static final Logger log = LoggerFactory.getLogger(EmailApplicationListener.class);
            @Override
            public void onApplicationEvent(MyEvent event) {
                log.debug("发送邮件");
            }
        }
    
    }
    
  • 2、@EventListener 标注监听方法

    • 根据监听器方法参数确定事件类型

    • 解析时机:在 SmartInitializingSingleton(所有单例初始化完成后),解析每个单例 bean

      @Configuration
      public class A48_2 {
          public static void main(String[] args) {
              AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_2.class);
              context.getBean(MyService.class).doBusiness();
              context.close();
          }
      
          static class MyEvent extends ApplicationEvent {
              public MyEvent(Object source) {
                  super(source);
              }
          }
      
          @Component
          static class MyService {
              private static final Logger log = LoggerFactory.getLogger(MyService.class);
              @Autowired
              private ApplicationEventPublisher publisher; // applicationContext
              public void doBusiness() {
                  log.debug("主线业务");
                  // 主线业务完成后需要做一些支线业务,下面是问题代码
                  publisher.publishEvent(new MyEvent("MyService.doBusiness()"));
              }
          }
          @Component
          static class SmsService {
              private static final Logger log = LoggerFactory.getLogger(SmsService.class);
              @EventListener
              public void listener(MyEvent myEvent) {
                  log.debug("发送短信");
              }
          }
      
          @Component
          static class EmailService {
              private static final Logger log = LoggerFactory.getLogger(EmailService.class);
              @EventListener
              public void listener(MyEvent myEvent) {
                  log.debug("发送邮件");
              }
          }
          //设置多线程
          @Bean
          public ThreadPoolTaskExecutor executor() {
              ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
              executor.setCorePoolSize(3);
              executor.setMaxPoolSize(10);
              executor.setQueueCapacity(100);
              return executor;
          }
      
          @Bean
          public SimpleApplicationEventMulticaster applicationEventMulticaster(ThreadPoolTaskExecutor executor) {
              SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster();
              multicaster.setTaskExecutor(executor);
              return multicaster;
          }
      }
      

    可以设置多线程实现异步监听

  • 3、自定义注解实现监听

    package com.example.springevent.a48;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.SmartInitializingSingleton;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationEvent;
    import org.springframework.context.ApplicationEventPublisher;
    import org.springframework.context.ApplicationListener;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.stereotype.Component;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    /**
     * @author: liang
     * @DATE: 2023/1/3
     * @PACKAGE_NAME: com.example.springevent.a48
     * @NAME: A48_3
     * @PROJECT_NAME: 自定义注解
     **/
    @Configuration
    public class A48_3 {
        public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_3.class);
            context.getBean(MyService.class).doBusiness();
            context.close();
    
        }
    
        /**
         * * 单例初始化后被调用
         * @param context
         * @return
         */
        @Bean
        public SmartInitializingSingleton smartInitializingSingleton(ConfigurableApplicationContext context){
            return  new SmartInitializingSingleton(){
                @Override
                public void afterSingletonsInstantiated() {
                    for (String name : context.getBeanDefinitionNames()) {
                        Object bean = context.getBean(name);
                        //获取方法对象
                        for (Method method : bean.getClass().getMethods()) {
                            //判断方法对象是否存在MyListener注解,适配器模式
                            if (method.isAnnotationPresent(MyListener.class)) {
                                ApplicationListener listener = new ApplicationListener<ApplicationEvent>() {
                                    @Override
                                    public void onApplicationEvent(ApplicationEvent event) {
                                        System.out.println(event);
                                        //监听器方法需要的事件类型
                                        Class<?> eventType = method.getParameterTypes()[0];
                                        if (eventType.isAssignableFrom(event.getClass())){
                                            try {
                                                method.invoke(bean,event);
                                            } catch (Exception e) {
                                                e.printStackTrace();
                                            }
                                        }
                                    };
                                };
                                //将listener加入到监听器中,让context知道
                                context.addApplicationListener(listener);
                            }
                        }
                    }
                }
            };
    
        }
    
        @Component
        static class MyService {
            private static final Logger log = LoggerFactory.getLogger(MyService.class);
            @Autowired
            private ApplicationEventPublisher publisher; // applicationContext
    
            public void doBusiness() {
                log.debug("主线业务");
                // 主线业务完成后需要做一些支线业务,下面是问题代码
                publisher.publishEvent(new MyEvent("MyService.doBusiness()"));
            }
        }
    
        @Component
        static class SmsService {
            private static final Logger log = LoggerFactory.getLogger(SmsService.class);
    
            @MyListener
            public void listener(MyEvent myEvent) {
                log.debug("发送短信");
            }
        }
    
        @Component
        static class EmailService {
            private static final Logger log = LoggerFactory.getLogger(EmailService.class);
    
            @MyListener
            public void listener(MyEvent myEvent) {
                log.debug("发送邮件");
            }
        }
    	
        @Retention(RetentionPolicy.RUNTIME)
        @Target(ElementType.METHOD)
        @interface MyListener {
        }
    
        static class MyEvent extends ApplicationEvent {
            public MyEvent(Object source) {
                super(source);
            }
        }
    }
    
    

3.2、事件发布器

事件发布器模拟实现

  1. addApplicationListenerBean 负责收集容器中的监听器
    • 监听器会统一转换为 GenericApplicationListener 对象,以支持判断事件类型
  2. multicastEvent 遍历监听器集合,发布事件
    • 发布前先通过 GenericApplicationListener.supportsEventType 判断支持该事件类型才发事件
    • 可以利用线程池进行异步发事件优化
  3. 如果发送的事件对象不是 ApplicationEvent 类型,Spring 会把它包装为 PayloadApplicationEvent 并用泛型技术解析事件对象的原始类型
    • 视频中未讲解
@Configuration
public class A49 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A49.class);
        context.getBean(MyService.class).doBusiness();
        context.close();
    }

    static class MyEvent extends ApplicationEvent {
        public MyEvent(Object source) {
            super(source);
        }
    }

    @Component
    static class MyService {
        private static final Logger log = LoggerFactory.getLogger(MyService.class);
        @Autowired
        private ApplicationEventPublisher publisher; // applicationContext

        public void doBusiness() {
            log.debug("主线业务");
            // 主线业务完成后需要做一些支线业务,下面是问题代码
            publisher.publishEvent(new MyEvent("MyService.doBusiness()"));
        }
    }

    @Component
    static class SmsApplicationListener implements ApplicationListener<MyEvent> {
        private static final Logger log = LoggerFactory.getLogger(SmsApplicationListener.class);

        @Override
        public void onApplicationEvent(MyEvent event) {
            log.debug("发送短信");
        }
    }

    @Component
    static class EmailApplicationListener implements ApplicationListener<MyEvent> {
        private static final Logger log = LoggerFactory.getLogger(EmailApplicationListener.class);
        @Override
        public void onApplicationEvent(MyEvent event) {
            log.debug("发送邮件");
        }
    }

    @Bean
    public ThreadPoolTaskExecutor executor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(3);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(100);
        return executor;
    }
    @Bean
    public ApplicationEventMulticaster applicationEventMulticaster(ConfigurableApplicationContext context, ThreadPoolTaskExecutor executor){
        return new AbstractApplicationEventMulticaster() {
            private List<GenericApplicationListener> listeners = new ArrayList<>();
            //收集监听器
            @Override
            public void addApplicationListenerBean(String name) {
                ApplicationListener listener = context.getBean(name, ApplicationListener.class);
                //获取该监听器支持的事件类型
                ResolvableType type = ResolvableType.forClass(listener.getClass()).getInterfaces()[0].getGeneric();
                System.out.println("type = " + type);

                //将原始的listener封装为支持事件检查的listener
                GenericApplicationListener genericApplicationListener = new GenericApplicationListener() {

                    @Override
                    public void onApplicationEvent(ApplicationEvent event) {
                        listener.onApplicationEvent(event);
                    }
                    //判断是否支持某事件类型
                    @Override
                    public boolean supportsEventType(ResolvableType eventType) {
                        //判断eventType是否能赋值给type
                        return type.isAssignableFrom(eventType);
                    }
                };
                listeners.add(genericApplicationListener);
            }

            //发布事件
            @Override
            public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
                for (GenericApplicationListener listener : listeners) {
                    if (listener.supportsEventType(ResolvableType.forClass(event.getClass()))) {
                        listener.onApplicationEvent(event);
                    }

                }
            }
        };
    }

    abstract static class AbstractApplicationEventMulticaster implements ApplicationEventMulticaster {
         @Override
         public void addApplicationListener(ApplicationListener<?> listener) {

         }

         @Override
         public void addApplicationListenerBean(String listenerBeanName) {

         }

         @Override
         public void removeApplicationListener(ApplicationListener<?> listener) {

         }

         @Override
         public void removeApplicationListenerBean(String listenerBeanName) {

         }

         @Override
         public void removeApplicationListeners(Predicate<ApplicationListener<?>> predicate) {

         }

         @Override
         public void removeApplicationListenerBeans(Predicate<String> predicate) {

         }

         @Override
         public void removeAllListeners() {

         }

         @Override
         public void multicastEvent(ApplicationEvent event) {

         }

         @Override
         public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {

         }
     }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值