ApplicationEvent的应用

事件驱动

事件:就是发生了什么事情,比如支付、扣款、过期等等就会发出通知,告诉相关业务系统发生了这件事

监听:监听相关系统发送的通知,从而做出处理

 

需求描述:创建订单完毕,需要给客户发送消息,然后缓存用户订单信息。删除订单时,需要按照顺序,先发短信,再清理缓存,再做其他操作

1:定义订单创建的事件源

package com.demo.ddd.event;

import com.demo.ddd.entity.Order;
import org.springframework.context.ApplicationEvent;

/**
 * 订单事件源*/
public class OrderEvent extends ApplicationEvent {

    private Order order;

    public Order getOrder() {
        return order;
    }

    public void setOrder(Order order) {
        this.order = order;
    }

    public OrderEvent(Object source) {
        super(source);
    }

    public OrderEvent(Object source, Order order) {
        super(source);
        this.order = order;
    }
}

2:创建订单生成监听类

创建的时候使用异步的方式,在主类上增加@EnableAsync,在方法上增加@Async 就实现了异步

package com.demo.ddd.event;

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

/**
 * 事件订阅处理 注解方式
 **/
@Component
@Slf4j
public class EventHandler {

    @EventListener(OrderEvent.class) //监听的事件源类
    @Async //异步
    public void orderStart(OrderEvent orderEvent) {
        // TODO 给客户发送短信逻辑
        System.out.println(Thread.currentThread().getName() + "发送短信提醒客户完毕!客户信息:" + orderEvent.getOrder().getCustomerDTO());
    }

    @EventListener(OrderEvent.class)
    @Async //异步
    public void orderEvent(OrderEvent orderEvent) {
        // TODO 订单缓存逻辑
        System.out.println(Thread.currentThread().getName() + "订单缓存完毕!客户信息:" + orderEvent.getOrder().getCustomerDTO());
    }

}

3:创建删除订单事件源

package com.demo.ddd.event;

import com.demo.ddd.entity.Order;
import org.springframework.context.ApplicationEvent;

/**
 * 订单删除事件源*/
public class OrderRemoveEvent extends ApplicationEvent {

    private Order order;

    public Order getOrder() {
        return order;
    }

    public void setOrder(Order order) {
        this.order = order;
    }

    public OrderRemoveEvent(Object source) {
        super(source);
    }

    public OrderRemoveEvent(Object source, Order order) {
        super(source);
        this.order = order;
    }
}

4:创建订单删除事件监听

删除事件 采用另一种继承的方式实现

package com.demo.ddd.event;

import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 控制顺序的继承方式
 **/
@Component
@Order(1) //数字越小,越优先执行
public class OrderRemoveEventHandler implements ApplicationListener<OrderRemoveEvent> { //泛型里是监听的事件源类

    @Override
    public void onApplicationEvent(OrderRemoveEvent event) {
        System.out.println(Thread.currentThread().getName() + "删除订单事件第一步!发送短信:" + event.getOrder());
    }
}

@Component
@Order(2)
class OrderRemoveCache implements ApplicationListener<OrderRemoveEvent> {

    @Override
    public void onApplicationEvent(OrderRemoveEvent event) {
        System.out.println(Thread.currentThread().getName() + "删除订单事件第二步!清理缓存:" + event.getOrder());
    }
}


@Component
@Order(3)
class OrderRemove implements ApplicationListener<OrderRemoveEvent> {

    @Override
    public void onApplicationEvent(OrderRemoveEvent event) {
        System.out.println(Thread.currentThread().getName() + "删除订单事件第三步!其他处理:" + event.getOrder());
    }
}

5:发布事件

package com.demo.ddd;

import com.demo.base.BaseContextService;
import com.demo.context.OrderContext;
import com.demo.ddd.entity.Order;
import com.demo.ddd.event.OrderEvent;
import com.demo.ddd.event.OrderRemoveEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

/**
 *订单业务*/
@Service
public class OrderApplicationService {

    private ApplicationContext applicationContext;

    public OrderApplicationService(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public boolean save(OrderDTO orderDTO) {

        // TODO 1:保存订单// 2:发送消息
        applicationContext.publishEvent(new OrderEvent(this, cover));
        return true;
    }

    public boolean remove(OrderDTO orderDTO) {
        // TODO 1:删除订单// 2:发送消息
        applicationContext.publishEvent(new OrderRemoveEvent(this, cover));
        return true;
    }
}

6:访问测试

这是一个springboot工程,其他都很简单,就不贴代码了

点击保存

 

控制台打印信息

 

 

 

点击删除

 

 

 

 

 控制台打印

 

 

原理

1:通过断点先进入publishEvent方法

 

 

 2:进入下一步到达这个位置

 

 

 3:从一个bean集合中取出对应的Listener

 

 

 

 4:拿到目标以后

循环执行

 

 

 5:最后执行的这个方法的

 

 

 

 6:看到这里就明白了 通过观察者模式,在发布的时候,根据类型去retrieverCache 缓存查找响应的Listener,然后执行onApplicationEvent方法,而这个方法 正是我们监听重写的方法,注解模式虽然我们定义的名字不一样,但是注解底层最终也是通过ApplicationListener对我们的方法进行实现的。需要注意的是,我们第一次系统启动时,我们自定义的监听类是不会被缓存起来的,所以在处理一些底层细节上,需要留意这一点,如果有特殊需要,则需要再系统启动之初,在代码级别自动触发一次,它就能缓存起来。具体逻辑可以参考下图:

 

posted @ 2023-04-13 15:05  鸭猪是的念来过倒  阅读(103)  评论(0编辑  收藏  举报