Spring的Event使用及说明

 更新时间:2026年03月30日 09:23:29   作者:楠~枫  
本文介绍了Spring中的事件机制,包括事件的实现方式、推送、监听器、异步事件、事件异常处理器等,并简要讲述了Java自带的观察者模式和事件机制

1、简介

只要是事件就是观察者模式,Spring中的Event也不例外,主要应用就是程序解耦,实现本质是广播的形式........话不多说

2、Spring的event实现方式

继承ApplicationEvent即可,但是Spring版本4.2之后不再强制要求继承ApplicationEvent,非Application的子类将被封装成PayloadApplicationEvent:

实现:

import org.springframework.context.ApplicationEvent;

public class MyEvent extends ApplicationEvent {
    //todo -----  
    private String msg;

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

    public MyEvent(Object source,String msg) {
        super(source);
        this.msg=msg;
    }

    public String getMsg() {
        return msg;
    }
}

3、事件的推送

编写事件推送的service实现ApplicationContextAwar接口,或者实现ApplicationEventPublisherAware接口,在需要时候根据业务场景推送事件:

实现:

@Service
public class EventProduceService implements ApplicationContextAware, ApplicationEventPublisherAware {
    //实现方式一
    private ApplicationContext applicationContext;
    //实现方式二
    private ApplicationEventPublisher applicationEventPublisher;

    /**
     * 容器初始化时候会自动的填装该对象
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     *  容器初始化时候会自动的填装该对象
     * @param applicationEventPublisher
     */
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher=applicationEventPublisher;
    }


    /**
     * 实际业务中进行封装数据推送
     */
    public void sentEvent(){
        //方式一:applicationContext的推送Api可以以根据需要进行选择
        applicationContext.publishEvent(new MyEvent(this,"我是一颗小码农"));
        //方式二: applicationEventPublisher的推送Api可以以根据需要进行选择
        applicationEventPublisher.publishEvent(new MyEvent(this,"今天是20220804"));
    }
}

4、事件监听器(处理器)

编写事件的处理器,交给Spring的ioc管理即可,实现有两种方式,

(1)通过@EventListener注解标注对应的事件处理器,处理器会根据参数类型自动识别事件类型的

实现:

@Configuration
public class EventConfig {
    @EventListener
    public void doWithEvent(MyEvent myEvent) {
        System.out.println("事件消息是: "+myEvent.getMsg());
    }

   @EventListener
   public void doWithEvent(BEvent myEvent) {
       System.out.println("事件消息是: "+myEvent.getMsg());
   }

    @EventListener
    public void doWithEvent(CEvent myEvent) {
        System.out.println("事件消息是: "+myEvent.getMsg());
    }
}

(2) 实现ApplicationListener<T>接口,处理器会根据泛型类型处理事件

实现

@Component
public class EventHandler implements ApplicationListener<MyEvent> {

    @Override
    public void onApplicationEvent(MyEvent event) {
        //todo----
        System.out.println(event.getMsg());
    }
}

5、异步事件

Spring默认监控的事件都是同步的,实现异步事件就需要开启异步事件的支持,配置类上使用@EventListener注解开启异步支持,然后在监听器上使用@Async注解标注即可,同一个事件多个处理器可以使用@Order注解进行排序(参数越小优先级越高)

实现:

@Configuration
@EnableAsync
public class EventConfig {
    @Async
    @EventListener
    public void doWithEvent(MyEvent myEvent) {
        System.out.println("事件消息是: "+myEvent.getMsg());
    }
}


@Async//配置类已经开启异步支持
@Component
public class EventHandler implements ApplicationListener<MyEvent> {

    @Override
    public void onApplicationEvent(MyEvent event) {
        //todo----
        System.out.println(event.getMsg());
    }
}

6、事件异常处理器(事件消费方出现异常进行必要处理)

(1) 同步的:

编写异常处理器实现 org.springframework.util.ErrorHandler

import org.springframework.stereotype.Component;
import org.springframework.util.ErrorHandler;

//同步方式异常处理器
@Component
public class DoExphandler implements ErrorHandler {
    /**
     * 只要在SimpleApplicationEventMulticaster设置这个异常处理器,
     * 事件消费方抛出异常就会触发这个方法中的异常,SimpleApplicationEventMulticaster.setErrorHandler(exphandler);
     */
    @Override
    public void handleError(Throwable e) {
        if (e instanceof RuntimeException) {
            //todo
        } else {
        }
    }
}

 在SimpleApplicationEventMulticaster事件广播中设置消费事的异常处理器

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;

@Service
public class EventProduceService implements ApplicationContextAware, ApplicationEventPublisherAware {
    //实现方式一
    private ApplicationContext applicationContext;
    //实现方式二
    private ApplicationEventPublisher applicationEventPublisher;

    //事件推送类注入广播处理同步异常
    @Autowired
    private SimpleApplicationEventMulticaster saem;

    @Autowired
    private DoExphandler exphandler;


    /**
     * 容器初始化时候会自动的填装该对象
     *
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 容器初始化时候会自动的填装该对象
     *
     * @param applicationEventPublisher
     */
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }



    public void sentEvent2(Object msg) {
        applicationContext.publishEvent(new MyEvent2((String) msg));
    }


    /**
     * 设置初始化的事件异常处理器
     */
    @PostConstruct
    public void  init(){
        saem.setErrorHandler(exphandler);
    }


}

(2)异步的:

编写异步事件处理器异常类,实现AsyncUncaughtExceptionHandler接口

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;


@Component
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
    @Override
    public void handleUncaughtException(Throwable ex,
                                        Method method,
                                        Object... params) {
        //todo,做相关处理
        ex.printStackTrace();
    }
}

做异步事件异常配置:

实现AsyncConfigurer接口

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;

import java.util.concurrent.Executor;

@Configuration
public class AsyncConfig implements AsyncConfigurer {
    @Autowired
    private AsyncExceptionHandler asyncExceptionHandler;

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return asyncExceptionHandler;
    }

    @Override
    public Executor getAsyncExecutor() {
        System.out.println("getAsyncExecutor");
        return AsyncConfigurer.super.getAsyncExecutor();
    }
}

7、java自带的事件

(1)观察者模式:

  • 作用:解耦,解耦....其他都是废话
  • 模式工作思想:a观察b,b做出某些动作后,a就及时的做动作的跟进 (至于a做啥,看你需要他做啥)
  • 设计思想:a根据b的状态变化做出响应,一般情况下都是多个对象观察一个对象,此时被观察者b就需要感知到都有哪些对象在观察自己 (设置集合存储这些对象)
  • 观察者:(在java.util.Observer已经做了顶层接口)
public  interface  MyObserver {
  void  update(ObserverHandler handler);
}

class MyObserverImp implements MyObserver{
  private int status;

  /**
   * 根据被观察者对象适应自身动作
   * @param handler 被观察者对象
   */
  @Override
  public void update(ObserverHandler handler) {
    status=((Handler)handler).getStatus();
  }

被观察者:(java.util. Observable已经做了适应)

interface ObserverHandler {
    //存储观察者,感知都有那些对象在观察
    List<MyObserver> list = new ArrayList<>();
}

class Handler implements ObserverHandler {
    private int status;

    public void setStatus(int status) {
        this.status = status;
        updateAllStatus();
    }

    public int getStatus() {
        return status;
    }

    public void updateAllStatus() {
        for (MyObserver myObserver : list) {
            myObserver.update(this);
        }
    }

    public void addObserver(MyObserver observer) {
        list.add(observer);
    }

    public void removeObserver(MyObserver observer) {
        list.remove(observer);
    }
}

(2)java的事件:

创建事件继承java.util.EventObject

public class UserEvent extends EventObject {

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

class SendMessageEvent extends UserEvent {

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

class SendFileEvent extends UserEvent {

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

创建事件监听器继承:java.util.EventListener

interface UserListener extends EventListener {
    static final ConcurrentHashMap<Object, Object> map = new ConcurrentHashMap<>();

    void doWithEvent(UserEvent event);
}

class Listener implements UserListener {

    @Override
    public void doWithEvent(UserEvent event) {
        if (event instanceof SendFileEvent) {
            System.out.println(event);
        } else if (event instanceof SendMessageEvent) {
            System.out.println(event);
        }
    }
}

推送事件

class SendEventHandler {

    private static UserListener listener = new Listener();

    public static void main(String[] args) {
        final SendMessageEvent sentMessage = new SendMessageEvent("发送事件");
        final SendFileEvent sendFile = new SendFileEvent("发送文件");
        listener.doWithEvent(sentMessage);
        listener.doWithEvent(sendFile);
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SSM 实现登录验证码功能(附源码)

    SSM 实现登录验证码功能(附源码)

    这篇文章主要介绍了SSM 实现登录验证码功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-12-12
  • Spring JDBC参数处理与嵌入式数据库的实战指南

    Spring JDBC参数处理与嵌入式数据库的实战指南

    这篇文章介绍了Spring Framework中JDBC的支持,包括如何处理参数和数据值、处理BLOB和CLOB、为IN子句传递列表以及存储过程调用中的复杂类型,本文用通俗易懂的方式讲解Spring JDBC参数处理与嵌入式数据库的相关操作,感兴趣的朋友跟随小编一起看看吧
    2025-10-10
  • 关于ReentrantLock原理全面解读

    关于ReentrantLock原理全面解读

    这篇文章主要介绍了关于ReentrantLock原理全面解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • java中 Map<String,Object>用法(示例代码整合)

    java中 Map<String,Object>用法(示例代码整合)

    Java中Map<String, Object>是参数化接口,用于存储键值对(键为String,值为Object),适用于动态数据存储、配置信息及JSON处理,需注意类型转换和空指针异常,下面通过示例代码给大家介绍java中 Map<String,Object>用法,感兴趣的朋友一起看看吧
    2025-07-07
  • Java设计模式 模板模式及应用场景解析

    Java设计模式 模板模式及应用场景解析

    这篇文章主要介绍了Java设计模式 模板模式及应用场景解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-07-07
  • MyBatis处理大字段或BLOB、CLOB类型数据方式

    MyBatis处理大字段或BLOB、CLOB类型数据方式

    这篇文章主要介绍了MyBatis处理大字段或BLOB、CLOB类型数据方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-04-04
  • Java实现用户短信验证码登录功能实例代码

    Java实现用户短信验证码登录功能实例代码

    现在不管是各类的网站,还是大小社交app,登录方式是越来越多了,但是大部分还是以短信登录为主,本文主要介绍了java短信验证码登录功能设计与实现,感兴趣的可以了解一下
    2021-11-11
  • Java中tomcat memecached session 共享同步问题的解决办法

    Java中tomcat memecached session 共享同步问题的解决办法

    这篇文章主要介绍了Java中tomcat memecached session 共享同步问题的解决办法的相关资料,需要的朋友可以参考下
    2015-10-10
  • Java中关于字符串的编码方式

    Java中关于字符串的编码方式

    这篇文章主要介绍了Java中关于字符串的编码方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • java如何根据用户请求获取ip地址并解析省市信息

    java如何根据用户请求获取ip地址并解析省市信息

    根据当前用户本地IP地址,查询IP地址库,获取IP所在的省市信息,目前有多种方式实现该功能,这篇文章主要给大家介绍了关于java如何根据用户请求获取ip地址并解析省市信息的相关资料,需要的朋友可以参考下
    2023-12-12

最新评论