zxpnet网站 zxpnet网站
首页
前端
后端服务器
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

zxpnet

一个爱学习的java开发攻城狮
首页
前端
后端服务器
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 大后端课程视频归档
  • 南航面试题
  • 并发编程

  • 性能调优

  • java8语法

  • lombok

  • 日志

  • 工具类

  • spring

  • mybatis

  • springboot

  • redis

  • zookeeper

  • springcloud

  • dubbo

  • netty

  • springsecurity

  • mq消息中间件

  • shiro

  • beetle

  • 模板引擎

  • jpa

  • 数据结构与算法

  • 数据库知识与设计

  • gradle

  • maven

  • bus

  • 定时任务

  • docker

  • centos

  • 加解密

  • biz业务

    • 公共业务

      • 单例模式
      • Untitled
      • 接口与抽象类的应用(包括各自设计模式)
      • SpringBoot使用ApplicationEvent&Listener完成业务解耦
        • 原理
          • 第一步:定义监听事件,继承ApplicationEvent
          • 第二步:定义监听器
          • 第三步:发送监听事件
          • 第四步:异步监听
        • 事例一:用户注册
      • 业务异常处理
      • ThreadLocal用法
      • 自定义RequestMappingHandlerMapping实现程序版本控制
    • 商城系统

    • 许愿池

    • 微信公众号

    • 企业微信

    • 分销返利系统

  • pigx项目

  • 开源项目

  • 品达通用权限项目-黑马

  • 货币交易项目coin-尚学堂

  • php

  • backend
  • biz业务
  • 公共业务
shollin
2021-06-24
目录

SpringBoot使用ApplicationEvent&Listener完成业务解耦

  • 原理
    • 第一步:定义监听事件,继承ApplicationEvent
    • 第二步:定义监听器
    • 第三步:发送监听事件
    • 第四步:异步监听
  • 事例一:用户注册

# 原理

  • 分为项目启动时的事件监听 ,结合/META-INF/spring.fatories使用。springboot自带的ApplicationEvent监听事件,如 ApplicationStartedEvent

  • 和应用运行时的事件监听。可以自定义监听事件

# 第一步:定义监听事件,继承ApplicationEvent

# 第二步:定义监听器

定义监听器有三种定义方式:

  • 方式一:利用注解@EventListener

  • 方式二:利用ApplicationListener

  • 方式三:利用SmartApplicationListener ,可以实现多个监听器有顺序地监听

一个事件可以被多个监听器监听;事件监听是无序的,监听到的事件先后顺序完全随机出现的, 要想有序就采用第三种方式

# 第三步:发送监听事件

applicationEventPublisher.publishEvent(new UserRegisterEvent(this,user));


@Service
public class UserService {

    @Autowired
    ApplicationEventPublisher applicationEventPublisher;

    /**
     * 用户注册方法
     * @param user
     */
    public void register(User user)
    {
        //../省略其他逻辑

        //发布UserRegisterEvent事件
        applicationEventPublisher.publishEvent(new UserRegisterEvent(this,user));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 第四步:异步监听

使用异步注解 ,@Aysnc是Spring内的一个组件,可以完成对类内单个或者多个方法实现异步调用,这样可以大大的节省等待耗时。内部实现机制是线程池任务ThreadPoolTaskExecutor,通过线程池来对配置@Async的方法或者类做出执行动作。

@Configuration
@EnableAsync
public class ListenerAsyncConfiguration implements AsyncConfigurer {

    /**
     * 获取异步线程池执行对象
     * @return
     */
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //此方法返回可用处理器的虚拟机的最大数量; 不小于1
        int core = Runtime.getRuntime().availableProcessors();
        //设置核心线程数
        executor.setCorePoolSize(core);
        //设置最大线程数
        executor.setMaxPoolSize(core * 2 + 1);
        //除核心线程外的线程存活时间
        executor.setKeepAliveSeconds(3);
        //如果传入值大于0,底层队列使用的是LinkedBlockingQueue,否则默认使用SynchronousQueue
        executor.setQueueCapacity(40);
        //线程名称前缀
        executor.setThreadNamePrefix("my-executor-");
        //设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//        return new LazyTraceThreadPoolTaskExecutor(beanFactory, executor);
        executor.initialize();

        return executor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }
}
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

# 事例一:用户注册

@Getter
public class UserRegisterEvent extends ApplicationEvent {

    //注册用户对象
    private User user;

    /**
     * 重写构造函数
     * @param source 发生事件的对象
     * @param user 注册用户对象
     */
    public UserRegisterEvent(Object source,User user) {
        super(source);
        this.user = user;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 第一种方式的监听器
@Component
public class AnnotationRegisterListener {
    /**
     * 注册监听实现方法
     * @param userRegisterEvent 用户注册事件
     */
    @EventListener
    public void register(UserRegisterEvent userRegisterEvent)
    {
        //获取注册用户对象
        User user = userRegisterEvent.getUser();

        //../省略逻辑

        //输出注册用户信息
        System.out.println("@EventListener注册信息,用户名:"+user.getName()+",密码:"+user.getPassword());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 第二种方式的监听器
@Component
public class RegisterListener implements ApplicationListener<UserRegisterEvent>
{
    /**
     * 实现监听
     * @param userRegisterEvent
     */
    @Override
    public void onApplicationEvent(UserRegisterEvent userRegisterEvent) {
        //获取注册用户对象
        User user = userRegisterEvent.getUser();

        //../省略逻辑

        //输出注册用户信息
        System.out.println("注册信息,用户名:"+user.getName()+",密码:"+user.getPassword());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Component
public class RegisterListenerSmartPrint implements SmartApplicationListener {
    /**
     * 该方法返回true&supportsSourceType同样返回true时,才会调用该监听内的onApplicationEvent方法
     * @param eventType 接收到的监听事件类型
     * @return boolean
     */
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        return eventType == UserRegisterEvent.class;
    }

    /**
     *  该方法返回true&supportsEventType同样返回true时,才会调用该监听内的onApplicationEvent方法
     * @param sourceType 接收到的监听事件类型
     * @return boolean
     */
    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        return sourceType == UserService.class;
    }

    /**
     *  supportsEventType & supportsSourceType 两个方法返回true时调用该方法执行业务逻辑
     * @param event 具体监听实例,这里是UserRegisterEvent
     */
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        //转换事件类型
        UserRegisterEvent userRegisterEvent = (UserRegisterEvent) event;
        //获取注册用户对象信息
        User user = userRegisterEvent.getUser();
        //.../完成注册业务逻辑
        System.out.println("注册信息,用户名:"+user.getName()+",密码:"+user.getPassword());
    }

    /**
     * 同步情况下监听执行的顺序
     * @return int
     */
    @Override
    public int getOrder() {
        return 0;
    }
}
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
41
42
43
44
45
@Component
public class RegisterListenerSmartEmail implements SmartApplicationListener {
    /**
     * 该方法返回true&supportsSourceType同样返回true时,才会调用该监听内的onApplicationEvent方法
     * @param eventType 接收到的监听事件类型
     * @return boolean
     */
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
        // 只有UserRegisterEvent监听类型才会执行下面逻辑
        return eventType == UserRegisterEvent.class;
    }

    /**
     *  该方法返回true&supportsEventType同样返回true时,才会调用该监听内的onApplicationEvent方法
     * @param sourceType 接收到的监听事件类型
     * @return boolean
     */
    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        // 只有在UserService内发布的UserRegisterEvent事件时才会执行下面逻辑
        return sourceType == UserService.class;
    }

    /**
     *  supportsEventType & supportsSourceType 两个方法返回true时调用该方法执行业务逻辑
     * @param event 具体监听实例,这里是UserRegisterEvent
     */
    @Override
    @Async
    public void onApplicationEvent(ApplicationEvent event) {
        try {
            //睡3秒钟
            Thread.sleep(3000);
        }catch (Exception e)
        {
            e.printStackTrace();
        }
        //转换事件类型
        UserRegisterEvent userRegisterEvent = (UserRegisterEvent) event;
        //获取注册用户对象信息
        User user = userRegisterEvent.getUser();
        System.out.println("用户:"+user.getName()+",注册成功,发送邮件通知。");
    }

    /**
     * 同步情况下监听执行的顺序
     * @return int
     */
    @Override
    public int getOrder() {
        return 1;
    }
}
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54

参考文档:

SpringBoot使用ApplicationEvent&Listener完成业务解耦 · 语雀 (yuque.com) (opens new window)

接口与抽象类的应用(包括各自设计模式)
业务异常处理

← 接口与抽象类的应用(包括各自设计模式) 业务异常处理→

最近更新
01
国际象棋
09-15
02
成语
09-15
03
自然拼读
09-15
更多文章>
Theme by Vdoing | Copyright © 2019-2023 zxpnet | 粤ICP备14079330号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式