Spring事件监听机制ApplicationEvent方式

 更新时间:2023年09月21日 09:02:52   作者:爱琴孩  
这篇文章主要介绍了Spring事件监听机制ApplicationEvent方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

前言

ApplicationEvent 以及 Listener 是Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业务逻辑之间的解耦,提高可扩展性以及可维护性。

ApplicationEvent的小demo

ApplicationEvent本身是抽象类,无法直接实例化。一般通过子类继承ApplicationEvent

public class MyApplicationEvent extends ApplicationEvent {
    private Student student;
    public Student getStudent() {
        return student;
    }
    public void setStudent(Student student) {
        this.student = student;
    }
    public MyApplicationEvent(Object source) {
        super(source);
    }
    public MyApplicationEvent(Object source, Student student) {
        super(source);
        this.student = student;
    }
}

事件定义好之后,我们注册个事件监听器即可。

实现ApplicationListener接口注册监听器

@Component
public class MyApplicationListener implements ApplicationListener<MyApplicationEvent> {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyApplicationListener.class);
    @Override
    public void onApplicationEvent(MyApplicationEvent myApplicationEvent) {
        Student student = myApplicationEvent.getStudent();
        LOGGER.info("学生对象是={}", JSONObject.toJSONString(student));
    }
}

通过@EventListener注册监听器,ApplicationContext.publishEvent 默认是同步操作, 并非发布后不管的异步操作,发布事件后需要等 @EventListener 执行完。

如果需要开启异步操作 需要在 @EventListener 上 增加 @Async 注解。

@Component
public class AsyncApplicationListener {
    private static final Logger LOGGER = LoggerFactory.getLogger(AsyncApplicationListener.class);
    @EventListener
    @Async
    public void listener(MyApplicationEvent myApplicationEvent) {
        Student student = myApplicationEvent.getStudent();
        LOGGER.info("通过@EventListener获取学生对象信息={}", JSONObject.toJSONString(student));
    }
}

通过实现SmartApplicationListener接口注册监听器

SmartApplicationListener接口继承了全局监听ApplicationListener,并且泛型对象使用的ApplicationEvent来作为全局监听,可以理解为使用SmartApplicationListener作为监听父接口的实现,监听所有事件发布。

既然是监听所有的事件发布,那么SmartApplicationListener接口添加了两个方法supportsEventType、supportsSourceType来作为区分是否是我们监听的事件,只有这两个方法同时返回true时才会执行onApplicationEvent方法。

@Component
public class MySmartApplicationListener implements SmartApplicationListener {
    private static final Logger LOGGER = LoggerFactory.getLogger(MySmartApplicationListener.class);
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) {
        return aClass == MyApplicationEvent.class;
    }
    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        return sourceType == ApplicationRunnerTest.class;
    }
    @Override
    public int getOrder() {
        return 0;
    }
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        MyApplicationEvent myApplicationEvent = (MyApplicationEvent) applicationEvent;
        LOGGER.info("通过MySmartApplicationListener 获取学生对象信息={}",
                JSONObject.toJSONString(myApplicationEvent.getStudent()));
    }
}

可以看到除了上面的方法,还提供了一个getOrder方法,这个方法就可以解决执行监听的顺序问题,return的数值越小证明优先级越高,执行顺序越靠前

发布事件

在Spring的Bean中,注入ApplicationContext ,通过ApplicationContext 来进行事件发布

@Autowired
private ApplicationContext applicationContext;
applicationContext.publishEvent(new MyApplicationEvent(this, new Student("爱琴孩", 18)));

运行结果

2023-01-28 10:38:39.696 YYZX_Study 13540 [           main]  INFO c.e.s.s.MySmartApplicationListener          37: 通过MySmartApplicationListener 获取学生对象信息={"age":18,"name":"爱琴孩"}
2023-01-28 10:38:39.696 YYZX_Study 13540 [           main]  INFO c.e.study.service.MyApplicationListener     22: 学生对象是={"age":18,"name":"爱琴孩"}
2023-01-28 10:38:39.696 YYZX_Study 13540 [tOrderService-1]  INFO c.e.s.service.AsyncApplicationListener      25: 通过@EventListener获取学生对象信息={"age":18,"name":"爱琴孩"}

总结

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

相关文章

  • 一次排查@CacheEvict注解失效的经历及解决

    一次排查@CacheEvict注解失效的经历及解决

    这篇文章主要介绍了一次排查@CacheEvict注解失效的经历及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 解决Hibernate4执行save()或update()无效问题的方法

    解决Hibernate4执行save()或update()无效问题的方法

    这篇文章主要为大家详细介绍了解决Hibernate4执行save()或update()无效问题的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • Idea热加载插件JRebel激活以及使用教程

    Idea热加载插件JRebel激活以及使用教程

    JRebel是一款JVM插件,它使得Java代码修改后不用重启系统,立即生效,下面这篇文章主要给大家介绍了关于Idea热加载插件JRebel激活以及使用的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • Java基于ServletContextListener实现UDP监听

    Java基于ServletContextListener实现UDP监听

    这篇文章主要介绍了Java基于ServletContextListener实现UDP监听,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • JAVA+Hibernate 无限级分类

    JAVA+Hibernate 无限级分类

    主要看menu_id和parent_id这两个字段。 Eclipse生成的表持久映射:(说明:自己加level属性,作用:为了记录种类所在深度)
    2008-07-07
  • 关于mybatis mapper类注入失败的解决方案

    关于mybatis mapper类注入失败的解决方案

    这篇文章主要介绍了关于mybatis mapper类注入失败的解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-04-04
  • Mybatis基于注解形式的sql语句生成实例代码

    Mybatis基于注解形式的sql语句生成实例代码

    这篇文章主要介绍了 Mybatis基于注解形式的sql语句生成实例代码,需要的朋友可以参考下
    2017-09-09
  • 详解SpringBoot中添加@ResponseBody注解会发生什么

    详解SpringBoot中添加@ResponseBody注解会发生什么

    这篇文章主要介绍了详解SpringBoot中添加@ResponseBody注解会发生什么,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • java随机字符补充版

    java随机字符补充版

    今天在zuidaimai看到一个java随机字符生成demo,正好要用,但发现不完整,重新整理一下,分享给有需要的朋友
    2014-01-01
  • 如何基于Java实现对象List排序

    如何基于Java实现对象List排序

    这篇文章主要介绍了如何基于Java实现对象List排序,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01

最新评论