Java Spring 事件监听详情解析

目录
  • 前言
  • 需求背景
  • 事件概念
    • 定义
    • 组成
  • 事件实现
  • 时序图

前言

前段时间因为工作的需要用到Spring事件,翻翻文档将功能实现了,但是存在少许理解不畅的地方,今天有空来梳理梳理。

需求背景

叶子同学在新入职公司,老大让他实现登陆功能,叶子随手写完,上线无bug,一切安好

//登陆伪代码
public void login(....){
    userLogin(....);
}

几天之后,老大说为维护用户的粘度,每天登陆送积分。叶子同学,二话不说,一顿操作后,上线无bug,一切安好

//登陆伪代码
public void login(....){
    //登陆
    userLogin(....);
    //送积分
    loginPoint(....)
}

又几天后,老大说,为了客户安全,每次异地登陆发送邮件。叶子同学稍微抱怨,看在钱份上又是一顿操作后,上线无bug, 一切安好

//登陆伪代码
public void login(....){
    //登陆
    userLogin(....);
    //送积分
    loginPoint(....)
    //发送邮件
    sendEmail(....)
}

又又几天后,老大说,部分客户不用邮件,用短信。叶子同学压着怒气,看着银行卡,又是一顿操作后,上线无bug, 一切安好

//登陆伪代码
public void login(....){
    //登陆
    userLogin(....);
    //送积分
    loginPoint(....)
    //发送邮件
    sendEmail(....)
    //发短信
    sendSms(...)
}

又又又几天后,老大还没开口,叶子同学就忍无可忍啦,得加钱。老大哄了好久,说不改需求了。改bug,用户抱怨登陆慢,有时还不成功。叶子二话不说,接手排查,查出问题啦

  • 1> 邮件发送耗时
  • 2>同步实现,如果邮件发送超时,登陆会出异常

代码改进:

//登陆伪代码
public void login(....){
    //登陆
    userLogin(....);

    try{
        //送积分
        new Thread(()->loginPoint(....)).start();

        //发送邮件
        new Thread(()->sendEmail(....)).start();

        //发短信
        new Thread(()->sendSms(....)).start();
    }catch(Exception e){
       //异常处理
    }
}

问题解决,功能实现,ok~

又又又又几天之后,老大说,只需要实现登陆功能即可,其他都不要~

叶子同学一句卧槽,然后是一段含母非常高的国粹。

此时,问:如果你是叶子同学,你有啥方案能优雅应对上面的需求变更呢?

一种优雅方案:事件监听机制

事件概念

定义

事件监听机制:就是对一个事件(行为动作)进行监听,当外界触发某事件时,监听程序马上被捕获该事件,并触发相应的响应,这过程称之为事件监听机制。

组成

事件监听机制有3个核心组成部分:

  • 1>事件,标记某种行为动作,比如:鼠标点击事件,鼠标移动事件等。
  • 2>事件源,被监控的对象或组件,事件发生的地方。比如:点击按钮,触发点击事件,按钮就是实现源。
  • 3>事件监听器,监听事件的操作类,一旦事件发生(被触发),则执行事件监听器预设的逻辑,进行事件响应。

  • 1>定义事件,并绑定到事件源中
  • 2>定义事件监听器,监听事件源
  • 3>用户某行为触发事件
  • 4>事件监听器监控到事件发送,执行事件响应逻辑。

以上面的登录为例:

  • 事件源:login方法
  • 事件:用户login行为
  • 事件监听器:此处没有,需要额外定制,但是事件响应:送积分,发邮件,发短信。

事件实现

以登录为例子实现事件监听机制

1>定义抽象事件

/**
 * 抽象事件类
 * 作用:定制事件逻辑
 */
public class AbstractEvent {
    //绑定的事件源
    private Object source;
    public AbstractEvent(Object source) {
        this.source = source;
    }
    public Object getSource() {
        return source;
    }
    public void setSource(Object source) {
        this.source = source;
    }
}

2>定制登陆事件

/**
 * 登陆事件
 */
public class LoginEvent extends AbstractEvent{
    public LoginEvent(Object source) {
        super(source);
    }
}

3>定义事件监听器

/**
 * 事件监听器
 * 作用:当监控的事件发送时,执行预设的逻辑
 */
public interface EventListener<E extends AbstractEvent> {

    /**
     * 预设逻辑方法
     * 事件被触发,马上执行
     */
    void onEvent(E event);
}

4>定制登陆事件监听器

积分监听器

/**
 * 加积分监听器器:
 * 当用户登陆事件触发后,马上执行
 */
public class PointsListener implements EventListener<LoginEvent> {
    public void onEvent(LoginEvent event) {
        System.out.println(event.getSource() + "发生后,执行积分+1操作");

        System.out.println(Thread.currentThread().getName());
    }
}

短信监听器

/**
 * 加积分监听器器:
 * 当用户登陆事件触发后,马上执行
 */
public class SmsListener implements EventListener<LoginEvent> {
    public void onEvent(LoginEvent event) {
        System.out.println(event.getSource() + "发生后,执行发送短信操作");
        System.out.println(Thread.currentThread().getName());
    }
}

邮件监听器

/**
 * 加积分监听器器:
 * 当用户登陆事件触发后,马上执行
 */
public class EmailListener implements EventListener<LoginEvent> {
    public void onEvent(LoginEvent event) {
        try {
            //模拟10s延时
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(event.getSource() + "发生后,执行发送邮件操作");
        System.out.println(Thread.currentThread().getName());
    }
}

5>定义事件广播器

/**
 * 事件广播器
 * 1>注册事件监听器
 * 2>删除事件监听器
 * 3>事件触发时,广播事件
 */
public interface EventMulticaster {
    //广播事件
    void multicastEvent(AbstractEvent event);

    //注册事件监听器
    void registListener(EventListener listener);

    //删除事件监听器
    void removeListener(EventListener listener);
}

6>定制简单的事件广播器

/**
 * 事件广播器实现类
 * 作用:维护事件监听器
 */
public class SimpleEventMulticaster implements EventMulticaster {
    //key:事件字节码对象, value:当前事件绑定的事件监听器
    private Map<Class<?>, List<EventListener>> map = new HashMap<Class<?>, List<EventListener>>();

    public void multicastEvent(AbstractEvent event) {
        List<EventListener> eventListeners = map.get(event.getClass());
        if(eventListeners != null){
            ExecutorService executorService = Executors.newCachedThreadPool();
            for (EventListener eventListener : eventListeners) {
                //异步
                executorService.submit(()-> eventListener.onEvent(event));
                //同步
                //eventListener.onEvent(event);
            }
            executorService.shutdown();
        }
    }
    public void registListener(EventListener listener) {
        //获取监听器绑定的事件
        ParameterizedType getType  = (ParameterizedType)listener.getClass().getGenericInterfaces()[0];
        Type type = getType.getActualTypeArguments()[0];
        Class<?> clz = (Class<?>) type;

        List<EventListener> listeners = map.get(clz);
        if(listeners == null){
            listeners = new ArrayList<EventListener>();
            map.put(clz, listeners);
        }
        listeners.add(listener);
    }
    public void removeListener(EventListener listener) {
        //获取监听器绑定的事件
        ParameterizedType getType  = (ParameterizedType)listener.getClass().getGenericInterfaces()[0];
        Type type = getType.getActualTypeArguments()[0];
        Class<?> clz = (Class<?>) type;

        List<EventListener> listeners = map.get(clz);
        if(listener != null){
            listeners.remove(listener);
        }

    }
}

7>综合测试

public class App {

    //1:初始化事件广播器
    public static SimpleEventMulticaster multicaster = new SimpleEventMulticaster();
    static {
        //2:注册监听器
        //登陆事件上绑定3个监听器
        multicaster.registListener(new PointsListener());
        multicaster.registListener(new EmailListener());
        multicaster.registListener(new SmsListener());
    }
    //3:模拟登陆
    public static void login(){
        //4:用户登陆成功触发登陆事件
        System.out.println("用户执行登陆逻辑");
        System.out.println(Thread.currentThread().getName());
        //5:广播登陆事件
        multicaster.multicastEvent(new LoginEvent("用户登陆啦"));
        System.out.println("登陆成功.....");
    }
    public static void main(String[] args) {
        App.login();
        System.out.println(Thread.currentThread().getName());
    }
}

时序图

到此这篇关于Java Spring 事件监听详情解析的文章就介绍到这了,更多相关Java 事件监听内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java事件监听机制讲解

    给组件加上监听器 定义一个类,这个类继承ActionListener pubulic class ButListener implements ActionListener{ Public void actionPerformed(ActionEvent e){ }} 给按钮添加动作监听器方法 ButListener but = new ButListen(); jbu.addActionListener(but); 加上监听机制后再监听器ButListener时间处理方法中再创建窗口即可得到点

  • Java基础学习之Swing事件监听

    一.初始代码架构 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class Btn extends JFrame{ public static void main(String []args){ JFrame f = new JFrame("事件监听测试"); f.setBounds(0,0,300,400); f.addWindowListener(new WindowAdapter(

  • java中接口和事件监听器的深入理解

    一:接口 接口在我们生活中无处不在,通过一个usb接口,我们可以通过u盘传输数据,这个接口是被定义过的,只有指定的类型能够使用这个接口,且通过这个接口我们传输的数据不会被破坏. 而在java中接口作用类似,定义一个具有特定特点的接口,在合适的地方引用它,执行所对应的功能,这样能够实现代码的分离. 下面我们来看一下接口的定义: 关键字:interface    格式:public interface 接口名{ } 接口的属性: [public static final]属性类型 属性名=属性值:

  • JAVA用户自定义事件监听实例代码

    JAVA用户自定义事件监听实例代码 很多介绍用户自定义事件都没有例子,或是例子不全,下面写了一个完整的例子,并写入了注释以便参考,完整的实例源代码如下: package demo; import Java.util.EventObject; /** * Title: 事件处理类,继承了事件基类 * Description: * Copyright: Copyright (c) 2005 * Company: cuijiang * @author not attributable * @versi

  • Java Swing中JList选择事件监听器ListSelectionListener用法示例

    本文实例讲述了Java Swing中JList选择事件监听器ListSelectionListener用法.分享给大家供大家参考,具体如下: 当JList中的元素被选中时,选择事件将被触发.对于JTable也是一样,你可以把它看做是多个并列的JList.那么,如果程序需要对该事件做出响应,需要以下步骤: (1)创建一个实现了 ListSelectionListener的监听器: (2)使用JList或selectionModel的addListSelectionListener添加监听器: (3

  • Java添加事件监听的四种方法代码实例

    Java添加事件的几种方式(转载了codebrother的文章,做了稍微的改动): /** * Java事件监听处理--自身类实现ActionListener接口,作为事件监听器 * * @author codebrother */ class EventListener1 extends JFrame implements ActionListener { private JButton btBlue, btDialog; public EventListener1() { setTitle(

  • java实现table添加右键点击事件监听操作示例

    本文实例讲述了java实现table添加右键点击事件监听操作.分享给大家供大家参考,具体如下: 表格监听步骤 1 给表格 添加监听addMouseListener 2 使用MouseAdapter类的mouseClicked方法 3 通过MouseEvent类对象的getbutton方法来判断鼠标操作 BUTTON1 为左键  BUTTON3 为右键 import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; imp

  • java开发gui教程之jframe监听窗体大小变化事件和jframe创建窗体

    复制代码 代码如下: import java.awt.event.WindowEvent;import java.awt.event.WindowStateListener; import javax.swing.JFrame; public class WinFrame extends JFrame { public WinFrame(){  this.setName("Window 窗口状态");  this.setSize(300,300);  this.setDefaultCl

  • JavaFX 监听窗口关闭事件实例详解

    1.写在前面 在JavaFX的程序开发的时候,在使用多线程的时候,默认情况下在程序退出的时候,新开的线程依然在后台运行. 在这种情况下,可以监听窗口关闭事件,在里面关闭子线程. 2.具体实现的样例 package sample; import javafx.application.Application; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import java

  • java-RGB调色面板的实现(事件监听器之匿名内部类)

    题目要求: 要求写一个案例,使用三个JSlider分别选取R.G.B三原色的值,用户可以通过活动JSlider的滑块来动态的合成一种颜色,合成的颜色显示在界面上. 代码思路解析: 1.所需要的组件 (1)JFrame窗口  (2)JLabel的RGB标签文字组件  (3)JTextField颜色变动的数值  (4)JSlider颜色交换的滑块组件  (5)JTextArea颜色显示区域 2.构造方法中将JFrame.JSlider.JTextField.JTextArea组件全部实例化 3.另写

随机推荐