栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot Event 观察者模式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot Event 观察者模式

前言

在我们实际业务开发过程中,往往会有核心业务+N多个子任务组成,都放在一块耦合度会不断升高,维护起来也会变得麻烦。还有一些业务场景不需要在一次请求中完成,例如发送短信等。
使用消息队列也可以解决这个问题,但是非必要的情况下不必提升架构复杂度。针对这些问题,我们了解一下 Spring Event。

使用步骤 一、Spring Event 同步使用

Spring Event(Application Event)其实就是一个观察者设计模式,一个 Bean 处理完成任务后希望通知其它 Bean 或者说一个 Bean 想观察监听另一个Bean 的行为。

1.自定义事件

定义事件,继承 ApplicationEvent 的类成为一个事件类

package com.example.demo.event;

import lombok.Data;
import org.springframework.context.ApplicationEvent;


@Data
public class OrderProductEvent extends ApplicationEvent {
    
    private String orderId;

    public OrderProductEvent(Object source, String orderId) {
        super(source);
        this.orderId = orderId;
    }
}
2.定义监听器

监听并处理事件,实现 ApplicationListener 接口或者使用 @EventListener 注解

package com.example.demo.event;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;


@Slf4j
@Component
public class OrderProductListener implements ApplicationListener {

    @SneakyThrows
    @Override
    public void onApplicationEvent(OrderProductEvent event) {
        String orderId = event.getOrderId();
        long start = System.currentTimeMillis();
        Thread.sleep(2000);
        long end = System.currentTimeMillis();
        log.info("收到监听校验商品价格,订单id为【{}】,用时:【{}】毫秒",orderId,end-start);
    }
}
3.定义发布者

发布事件,通过 ApplicationEventPublisher 发布事件

package com.example.demo.event;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;


@Slf4j
@Service
@RequiredArgsConstructor
public class OrderProductService {
    
    private final ApplicationContext applicationContext;

    
    public String bugOrder(String orderId){
        long start = System.currentTimeMillis();
        //1、其他业务操作
        log.info("开始下单");
        //2、检验订单价格(同步处理)
        applicationContext.publishEvent(new OrderProductEvent(this,orderId));
        //后续操作
        log.info("下单成功,返回结果");
        long end = System.currentTimeMillis();
        log.info("任务结束,全部耗时:【{}】",end-start);
        return "下单成功";
    }

}
4、执行
    @Autowired private OrderProductService orderProductService;
    @Test
    public void testEvent(){
        String result = orderProductService.bugOrder("12313131");
        System.err.println(result);
    }
5、结果

二、Spring Event 异步使用

有些业务场景不需要在一次请求中同步完成,比如邮件发送、短信发送等

1.开启异步

启动类增加 @EnableAsync 注解

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}
2.自定义事件
package com.example.demo.event;

import lombok.AllArgsConstructor;
import lombok.Data;


@Data
@AllArgsConstructor
public class MsgEvent {

    
    private String message;
}
3.定义监听器

推荐使用 @EventListener 注解,开启异步的方法增加 @Async 注解

package com.example.demo.event;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;


@Slf4j
@Component
public class MsgListener {

    @Async
    @SneakyThrows
    @EventListener(MsgEvent.class)
    public void sendMsg(MsgEvent msgEvent){
        String message = msgEvent.getMessage();
        long start = System.currentTimeMillis();
        log.info("开始发送短信");
        Thread.sleep(2000);
        long end = System.currentTimeMillis();
        log.info("发送短信,短信内容为:【{}】,耗时:【{}】",message,end-start);
    }
}
4.定义发布者
package com.example.demo.event;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;


@Slf4j
@Service
@RequiredArgsConstructor
public class OrderProductService {
    
    private final ApplicationContext applicationContext;

    
    public String bugOrder(String orderId){
        long start = System.currentTimeMillis();
        //1、其他业务操作
        log.info("开始下单");
        //2、检验订单价格(同步处理)
        applicationContext.publishEvent(new OrderProductEvent(this,orderId));
        //3、发送短信(异步处理)
        applicationContext.publishEvent(new MsgEvent("您好,正在执行下单操作"));
        //后续操作
        log.info("下单成功,返回结果");
        long end = System.currentTimeMillis();
        log.info("任务结束,全部耗时:【{}】",end-start);
        return "下单成功";
    }


}
5.执行
@Autowired private OrderProductService orderProductService;
@Test
public void testEvent(){
    String result = orderProductService.bugOrder("12313131");
    System.err.println(result);
}
6.结果

发送短信的线程显示 task-1,主线程结束后(总耗时:(2017)毫秒)控制台停止打印了

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1013103.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号