• 【四十八讲】事件-监听器


    第四十八讲 事件-监听器

    1. 实现ApplicationListener 接口
    2. 通过@EvenListener 方法
    3. @EventListener 原理

    ApplicationListener 接口

    事件

    static class MyEvent extends ApplicationEvent {
        public MyEvent(Object source) {
            super(source);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    主线

    @Component
    static class MyService{
        @Autowired
        private ApplicationEventPublisher publisher; // applicationContext
        public void doBusiness() {
            log.debug("主线业务");
            // 主线业务完成后需要做一些支线业务,下面是问题代码
            publisher.publishEvent(new MyEvent("MyService.doBusiness()"));
        }
    }
    
    ------------------------------------------
        public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_1.class);
        context.getBean(MyService.class).doBusiness();
        context.close();
    
    }    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    解耦后操作

    @Component
    static class SmsApplicationListener implements ApplicationListener<MyEvent> {
    
        @Override
        public void onApplicationEvent(MyEvent event) {
            log.debug("发送短信");
        }
    }
    
    ----------------------------------------------------------------------------
    @Component
    static class EmailApplicationListener implements ApplicationListener<MyEvent> {
        @Override
        public void onApplicationEvent(MyEvent event) {
            log.debug("发送邮件");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    通过@EvenListener 方法实现

    只需要修改解耦部分

    @Component
    static class SmsApplicationListener implements ApplicationListener<MyEvent> {
    
        @Override
        public void onApplicationEvent(MyEvent event) {
            log.debug("发送短信");
        }
    }
    
    ----------------------------------------------------------------------------
    @Component
    static class EmailApplicationListener implements ApplicationListener<MyEvent> {
        @Override
        public void onApplicationEvent(MyEvent event) {
            log.debug("发送邮件");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    @Component
    static class SmsApplicationListener {
        @EventListener
        public void listener(MyEvent event) {
            log.debug("发送短信");
        }
    }
    
    @Component
    static class EmailApplicationListener {
        @EventListener
        public void listener(MyEvent event) {
            log.debug("发送邮件");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    异步执行线程

    @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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    @EventListener 原理

    定义自己注解

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @interface MyListener {
    }
    
    • 1
    • 2
    • 3
    • 4

    替换注解

    @Component
    static class SmsApplicationListener {
        @MyListener
        public void listener(MyEvent event) {
            log.debug("发送短信");
        }
    }
    
    @Component
    static class EmailApplicationListener {
        @MyListener
        public void listener(MyEvent event) {
            log.debug("发送邮件");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
     public static void main(String[] args) {
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_3.class);
            SmsApplicationListener bean = context.getBean(SmsApplicationListener.class);
    
            for (Method method : SmsApplicationListener.class.getMethods()) {
                if(method.isAnnotationPresent(MyListener.class)){
                    ApplicationListener listener = new ApplicationListener() {
                        @Override
                        public void onApplicationEvent(ApplicationEvent event) {
                            // 监听器 方法需要的事件类型
                            System.out.println("事件---"+event);
                            Class<?> evenType = method.getParameterTypes()[0];// 
                            if(evenType.isAssignableFrom(event.getClass())){
                                try {
                                    method.invoke(bean,event);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    };
                    context.addApplicationListener(listener);
                }
            }
    
            context.getBean(MyService.class).doBusiness();
            context.close();
    
        }
    
    • 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

    在这里插入图片描述

    context.close 也会调用 ApplicationListener,所以反射的时候需要进行判断,不然会报错

    在这里插入图片描述

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

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_3.class);
    
        for (String name : context.getBeanDefinitionNames()) {
            Object bean = context.getBean(name);
            for (Method method : bean.getClass().getMethods()) {
                if(method.isAnnotationPresent(MyListener.class)){
                    ApplicationListener listener = new ApplicationListener() {
                        @Override
                        public void onApplicationEvent(ApplicationEvent event) {
                            // 监听器 方法需要的事件类型
                            System.out.println("事件---"+event);
                            Class<?> evenType = method.getParameterTypes()[0];//
                            if(evenType.isAssignableFrom(event.getClass())){
                                try {
                                    method.invoke(bean,event);
                                } catch (Exception e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    };
                    context.addApplicationListener(listener);
                }
            }
    
        }
    
        context.getBean(MyService.class).doBusiness();
        context.close();
    
    }
    
    • 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

    在这里插入图片描述

    利用SmartInitializingSingleton进行优化

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(A48_3.class);
        context.getBean(MyService.class).doBusiness();
        context.close();
    
    }
    
    -----------------
    @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()) {
                        if(method.isAnnotationPresent(MyListener.class)){
                            ApplicationListener listener = new ApplicationListener() {
                                @Override
                                public void onApplicationEvent(ApplicationEvent event) {
                                    // 监听器 方法需要的事件类型
                                    System.out.println("事件---"+event);
                                    Class<?> evenType = method.getParameterTypes()[0];//
                                    if(evenType.isAssignableFrom(event.getClass())){
                                        try {
                                            method.invoke(bean,event);
                                        } catch (Exception e) {
                                            e.printStackTrace();
                                        }
                                    }
                                }
                            };
                            context.addApplicationListener(listener);
                        }
                    }
    
                }
            }
        };
    }
    
    • 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
    • 37
    • 38
    • 39
    • 40
  • 相关阅读:
    【Docker从入门到入土 6】Consul详解+Docker https安全认证(附证书申请方式)
    基础算法(六):回溯算法
    国标GB28181协议客户端开发(一)整体流程和技术选型
    http和https分别是什么?
    Java攻略集合之基础语法
    Go访问MySQL数据库
    leetcode 2602. 使数组元素全部相等的最少操作次数
    并查集学习笔记
    2022年 maven配置阿里云仓库配置
    Doccano 修复 spacy.gold 的bug
  • 原文地址:https://blog.csdn.net/qq_25614773/article/details/126805676