Java 创建事件Event、事件监听EventListener、事件发布publishEvent

今天在看别人的代码时,看到Spring中事件发布publishEvent,所以特地查资料,学习一下,做个笔记。原文地址:Java 创建事件Event、事件监听EventListener、事件发布publishEvent_预立科技的博客-CSDN博客

一、概述
个人认为,事件机制一般可由:事件源source,事件对象Event,事件监听EventListener,事件发布publishEvent组成
事件源:引起事件发生的源; User用户信息, Order订单信息等为事件源数据,User登录状态loginStatus引起的事件, Order状态status引起的事件
事件对象:继承ApplicationEvent,事件对象包含事件源,事件对象也就是要被监听的对象; UserEvent, OrderEvent为事件对象,
事件监听:监听事件对象,事件对象被发布触发时,事件监听到后执行处理逻辑
事件发布:触发事件的发生


发布事件publishEvent后,EventListener监听到进行默认同步处理, 线程被阻塞, 这种同步方式吞吐量小耗时,不利用程序高并发。
在实际应用过程中,事件发布或事件监听后处理逻辑应该都是异步不阻塞线程。

publishEvent或EventListener 任意一个加上异步@Async即可(程序启动类必须要添加@EnableAsync)。推荐publishEvent加异步。
如果publishEven和EventListener过程中都有大量处理数据库或其他耗时的业务,也可以两者同时加上@Async

.

举例:
1.OrderEvent订单事件中,用户进行订单支付,订单支付逻辑处理完,同步返回给用户支付完成的消息,同时发布订单事件,异步处理订单发货逻辑等,这样可以将订单支付和订单发货解耦。
2.UserEvent用户事件中,用户登录成功后,同步返回给用户登录成功的消息,同时发布用户登录事件,异步处理用户登录后记日志登录日志, 写用户购物车缓存等逻辑

.

这种事件驱动机制其实是观察者模式(又称发布订阅)具体实现,事件对象(Event)相当于被观察对象(Subject), 事件监听(EventListener) 相当于观察者(Observer)

下面是简单的代码实现二、创建事件源

import lombok.Data;

@Data
public class User {

    private Long id;

    private String loginStatus;
}
package com.xxxx.model;
import lombok.Data;

@Data
public class Order {

    private Long id;

    private Integer status;
}


三、创建事件对象
例如:订单状态事件,用户状态事件, 需要继承ApplicationEvent

package com.xxxx.event;

import com.xxxx.model.Order;
import org.springframework.context.ApplicationEvent;

public class OrderEvent extends ApplicationEvent {

    private Order order;

    public OrderEvent(Order order) {
        //ApplicationEvent 构造函数中必须传入source对象,  官方注释中被定义为最初发生事件的对象
        super(order);
        //方式二
        //super(order.getId());
        order = order;
    }

    public Order getOrder(){
        return order;
    }
}


四、事件监听
方法上添加监听事件的注解@EventListener
方法的参数为继承ApplicationEvent的事件对象

package com.xxxx.event;

import com.xxxx.model.Order;
import com.xxxx.model.User;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class EventListenerHandle {

    /**
     * EventListener 监听到OrderEvent事件,触发方法
     * @param orderEvent
     */
    @Async
    @EventListener
    public void handle(OrderEvent orderEvent){
        Order order = orderEvent.getOrder();
        //getSource() 取决去构建OrderEvent时的super(source)
        //Object object = orderEvent.getSource();

        //处理订单业务
        if(order.getStatus() == 0){

        }else (order.getStatus() == 1){

        }else {

        }
    }

    /**
     * EventListener 监听到UserEvent事件,触发方法
     * @param userEvent
     */
    @Async
    @EventListener
    public void handle(UserEvent userEvent){
        User user = userEvent.getUser();
        
        //处理用户业务
        if(user.getLoginStatus() == 0){

        }else (user.getLoginStatus() == 1){

        }else {

        }
    }
}


五、事件发布
ApplicationContext应用上下文继承了ApplicationEventPublisher,可以调用发布事件

package com.xxxx.event;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.stereotype.Component;

@Component
public class EventPush {

    /**
     * ApplicationContext 继承实现了 ApplicationEventPublisher, 可以直接发布事件
     */
    @Autowired
    private ApplicationContext applicationContext;

    @Async
    public void publishEvent(ApplicationEvent event){
        if (event instanceof OrderEvent) {
            applicationContext.publishEvent((OrderEvent) event);
            return;
        } else if(event instanceof UserEvent) {
            applicationContext.publishEvent((UserEvent) event);
            return;
        } else {
            //发布失败
        }
    }

    @Async
    public void orderEventPush(OrderEvent event){
        applicationContext.publishEvent(event);
    }

    @Async
    public void userEventPush(UserEvent event){
        applicationContext.publishEvent(event);
    }
}


六、调用
注入依赖类

@Autowired
private EventPush eventPush;


调用事件发布

Order order = new Order();
order.setId(1000L);
//0: 订单创建成功  1:支付成功  .....
order.setStatus(1);

User user = new User();
user.setId(1000L);
//0: 退出成功  1:登录成功  .....
user.setLoginStatus(1);

//方式一:
eventPush.orderEventPush(new OrderEvent(order));
eventPush.userEventPush(new UserEvent(user));

//方式二:
eventPush.publishEvent(new OrderEvent(order));
eventPush.publishEvent(new UserEvent(user));

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值