2. Spring ApplicationListener进阶版

本文介绍了Spring的ApplicationListener的进阶使用,包括数据和事件的抽象,以及监听器的接口和实现优化。通过BaseSource和BaseEvent的定义,解决了事件处理的灵活性问题,并通过IEventListener接口规范了监听器的行为,确保了监听器之间的独立性和异常处理。示例展示了如何创建和使用这些抽象后的监听器来处理用户增删改事件。
摘要由CSDN通过智能技术生成

ApplicationListener系列文章

  1. ApplicationListener 基础版

  2. ApplicationListener 进阶版

  3. ApplicationListener源码版

  4. ApplicationListener 问题版

  5. ApplicationListener 扩展版

  6. ApplicationListener 总结版

上一篇文章,属于基础版ApplicationListener基础版,我们正常的业务使用,但是还有一些缺陷:

  1. 同一个数据的增删改,需要建立对应的操作事件。
  2. 没有提取公共部分,例如:Listener的互相影响问题,存在一个Listener出现异常,影响其他Listener的消费。

ApplicationListener进阶版

数据抽象

public class BaseSource implements Serializable {

    private String sourceType;

    public BaseSource(String sourceType) {
        this.sourceType = sourceType;
    }

    /**
     * 数据类型
     * 监听者根据类型,进行判断是否处理。
     * 类似MQ中的tag
     *
     * @return 数据类型
     */
    public String getSourceType() {
        return sourceType;
    }

    public boolean isDeleteOperate() {
        return EventSourceOperation.DELETE.getOperate().equals(getSourceType());
    }

    public boolean isAddOperate() {
        return EventSourceOperation.ADD.getOperate().equals(getSourceType());
    }

    public boolean isEditOperate() {
        return EventSourceOperation.EDIT.getOperate().equals(getSourceType());
    }


}


/**操作类型枚举*/
public enum EventSourceOperation {
    ADD("ADD", "新增"),
    EDIT("EDIT", "修改"),
    DELETE("DELETE", "删除");
    private final String operate;
    private final String desc;

    EventSourceOperation(String operate, String desc) {
        this.operate = operate;
        this.desc = desc;
    }

    public String getOperate() {
        return operate;
    }
}

事件抽象

抽象出BaseEvent,主要作用:

  1. 添加业务属性name。
  2. 解决ApplicationEvent获取Source时,返回Object,通过泛型解决Listener的类型转换。
public class BaseEvent<S extends BaseSource> extends ApplicationEvent {
    private String name;

    public BaseEvent(S s) {
        this("", s);
    }

    public BaseEvent(String name, S s) {
        super(s);
        this.name = name;

    }

    @Override
    public S getSource() {
        return (S) super.getSource();
    }

    public String getName() {
        return name;
    }
}

监听抽象

接口抽象

抽取公共接口,规定了监听需要具有的通用接口,让监听更完善。

public interface IEventListener<E extends BaseEvent> extends ApplicationListener<E> {

    /**
     * 是否支持,根据需要判断是否进行下一步
     *
     * @param event 事件
     * @return true=支持
     */
    boolean support(E event);


    /**
     * 处理事件,建议自行try catch
     *
     * @param event 事件
     */
    void handleEvent(E event);

    /**
     * 处理异常,如果没有try catch,会自动捕捉并包装异常
     *
     * @param event                事件
     * @param eventHandleException 事件处理过程中,出现的异常
     */
    void handleException(E event, EventHandleException eventHandleException);

}

基础实现

基础监听,实现IEventListener,同时对事件与数据进行剥离,原因:监听器,其实核心关心的是事件带有的数据,因此提供:BaseEventSourceListener,监听只需要关心Source即可。类似于:MQ消息,关心的不是消息,而是消息承载的内容。

public abstract class BaseEventSourceListener<E extends BaseEvent<S>, S extends BaseSource> implements IEventListener<E> {
    @Override
    public boolean support(E event) {
        return supportSource(event.getSource());
    }

    /**
     * 子类重写,是否支持事件中的数据,
     * 类似于:MQ中的tag判断,通过一个事件,承载不同处理的数据。
     *
     * @param source 数据
     * @return true=支持该数据
     */
    public abstract boolean supportSource(S source);


    @Override
    public void handleEvent(E event) {
        handleSource(event.getSource());
    }

    /**
     * 处理该事件的核心数据
     *
     * @param source 事件的核心:数据
     */
    public abstract void handleSource(S source);

	/**
     * 默认处理方式:
     * 包装异常,同时抛出特殊异常
     * */
    @Override
    public void handleException(E event, EventHandleException eventHandleException) {
        throw eventHandleException;
    }

    @Override
    public void onApplicationEvent(E event) {
        if (support(event)) {
        	//try catch的必要性,当多个Listener监听同一个事件时,防止监听之间的互相影响 
            try {
                handleEvent(event);
            } catch (Exception e) {
                handleException(event, new EventHandleException(e));
            }
        }
    }
}

示例监听

用户新增的监听

public class UserAddChangeListener extends BaseEventSourceListener<UserChangeEvent, UserChange> {
    @Override
    public boolean supportSource(UserChange source) {
        return source.isAddOperate();
    }

    @Override
    public void handleSource(UserChange source) {
        System.out.println("user change add:" + source.toString());
    }
}

用户删除的监听

public class UserDeleteChangeListener extends BaseEventSourceListener<UserChangeEvent, UserChange> {
    @Override
    public boolean supportSource(UserChange source) {
        return source.isDeleteOperate();
    }

    @Override
    public void handleSource(UserChange source) {
        System.out.println("user change delete:" + source.toString());
    }
}

发布事件


public static void main(String[] args) throws InterruptedException {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(UserAddChangeListener.class);
        applicationContext.register(UserDeleteChangeListener.class);
        applicationContext.refresh();

        applicationContext.publishEvent(new UserChangeEvent(UserChange.createAddOperation(1, "userAdd ")));
        applicationContext.publishEvent(new UserChangeEvent(UserChange.createDeleteOperation(1, "userDelete ")));
    }

结果输出

user change add:UserChange(id=1, name=userAdd )
user change delete:UserChange(id=1, name=userDelete )

源码版

Spring ApplicationListener源码版

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值