Spring的事件和监听器-同步与异步详解

 更新时间:2021年12月28日 10:25:11   作者:^破晓^  
这篇文章主要介绍了Spring的事件和监听器-同步与异步详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

Spring的事件和监听器-同步与异步

Application下抽象子类ApplicationContextEvent的下面有4个已经实现好的事件

  • ContextClosedEvent(容器关闭时)
  • ContextRefreshedEvent(容器刷新是)
  • ContextStartedEvent(容器启动时候)
  • ContextStoppedEvent(容器停止的时候)

同样,这四个事件都继承了ApplicationEvent,如果我们想自定义事件,也可以通过继承ApplicationEvent来实现

1、首先新建StartWorkflowEvent.java,

继承ApplicationEvent抽象类

public class StartWorkflowEvent extends ApplicationEvent {
    //存放构造器送入的值
    private String msg;
    //构造器参数可以随意设置,这里为了方便调试,设置为字符串
    public StartWorkflowEvent (String msg) {
        super(msg);
        this.msg=msg;
    }
    //自定义一个方法,这个方法也可以随意写,这里也是测试用
    public void myevent(){
        System.out.println("********My event**************");
        System.out.println(msg);
        System.out.println("*******************************");
    }
}

2、新建一个监听器StartWorkflowListener.java

实现ApplicationListener<StartWorkflowEvent>

/**
 * 发起流程事件监听
 */
@Component("startWorkflowListener")
public class StartWorkflowListener implements ApplicationListener<StartWorkflowEvent> {
 
    @Autowired
    private OaWorkflowHepler oaWorkflowHepler;
 
//@Async注解异步调用时使用, 异步调用时, 需要在xml配置文件中添加 <task:annotation-driven />
//  @Async
    @Override
    public void onApplicationEvent(StartWorkflowEvent event) {
        oaWorkflowHepler.start(event.getMsg());
    }
}

3、创建一个事件发布类EventPublisher.java

/**
 * 发布事件
 */
@Component("eventPublisher")
public class EventPublisher {
 
    @Autowired
    private ApplicationContext applicationContext;
 
    /**
     * 发布事件
     * @param event
     */
    public void publishEvent(ApplicationEvent event) {
        applicationContext.publishEvent(event);
    }
}

4、相关的配置

<task:annotation-driven />配置:

  • executor:指定一个缺省的executor给@Async使用。

例子:

<task:annotation-driven executor="asyncExecutor" />

<task:executor />配置参数:

  • id:当配置多个executor时,被@Async("id")指定使用;也被作为线程名的前缀。
  • core size:最小的线程数,缺省:1
  • max size:最大的线程数,缺省:Integer.MAX_VALUE
  • queue-capacity:当最小的线程数已经被占用满后,新的任务会被放进queue里面,当这个 queue的capacity也被占满之后,pool里面会创建新线程处理这个任务,直到总线程数达到了max size,这时系统会拒绝这个任务并抛出TaskRejectedException异常(缺省配置的情况下,可以通过rejection-policy 来决定如何处理这种情况)。缺省值为:Integer.MAX_VALUE
  • keep-alive:超过core size的那些线程,任务完成后,再经过这个时长(秒)会被结束掉
  • rejection-policy:当pool已经达到max size的时候,如何处理新任务
  • ABORT(缺省):抛出TaskRejectedException异常,然后不执行
  • DISCARD:不执行,也不抛出异常
  • DISCARD_OLDEST:丢弃queue中最旧的那个任务
  • CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行

Spring事件、异步监听

使用事件的模式可以对系统进行解耦,事件源发布一个事件,

事件监听器可以消费这个事件,而事件源不用关注发布的事件有哪些监听器,

这可以对系统进行解耦

在这里插入图片描述

public class Mains extends ApplicationEvent {
    public Mains(Object name) {
        super(name);
        System.out.println(String.format("Hi,我是被监听的%s!",name));
    }
}
@Component
public class ListenerMains {
    //@Async  // 开启异步就无法使用@Order(0)进行排序了
    @Order(0)
    @EventListener(Mains.class)
    public void listener(Mains mains){
        System.out.println("这是第一个监听类 "+mains.getSource());
    }
    //@Async
    @Order(1)
    @EventListener(Mains.class)
    public void listener2(Mains mains){
        System.out.println("这是第二个监听类 "+mains.getSource());
    }
    //@Async
    @Order(2)
    @EventListener(Mains.class)
    public void listener3(Mains mains){
        System.out.println("这是第三个监听类 "+mains.getSource());
    }
}
public class TestController {
    @Autowired
    GetAccessToken getAccessToken;
    @Autowired
    ApplicationEventPublisher publisher;
    @RequestMapping("test")
    public Object get() {
        publisher.publishEvent(new Mains("哈哈哈哈"));
    }
}

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

相关文章

  • SpringBoot整合Prometheus如何实现资源监控

    SpringBoot整合Prometheus如何实现资源监控

    本文介绍了如何使用Prometheus监控SpringBoot应用,Prometheus是一个开源的监控和告警工具,SpringBootActuator提供了监控和管理SpringBoot应用的工具,通过添加依赖、配置Actuator和Prometheus,可以实现对SpringBoot应用的实时监控
    2024-12-12
  • MyBatis 添加元数据自定义元素标签的实现代码

    MyBatis 添加元数据自定义元素标签的实现代码

    这篇文章主要介绍了MyBatis 添加元数据自定义元素标签的实现代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • Spring Boot应用程序中如何使用Keycloak详解

    Spring Boot应用程序中如何使用Keycloak详解

    这篇文章主要为大家介绍了Spring Boot应用程序中如何使用Keycloak详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • java邮件发送的实现

    java邮件发送的实现

    本篇是用于java来实现邮件的发送的实例代码,基于smtp服务,有需要的可以参考一下。
    2016-10-10
  • Java实现游戏抽奖算法

    Java实现游戏抽奖算法

    这篇文章主要为大家详细介绍了Java实现游戏抽奖算法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • Java中的阻塞队列BlockingQueue使用详解

    Java中的阻塞队列BlockingQueue使用详解

    这篇文章主要介绍了Java中的阻塞队列BlockingQueue使用详解,阻塞队列是一种线程安全的数据结构,用于在多线程环境下进行数据交换,它提供了一种阻塞的机制,当队列为空时,消费者线程将被阻塞,直到队列中有数据可供消费,需要的朋友可以参考下
    2023-10-10
  • Java中的stream流的概念解析及实际运用总结

    Java中的stream流的概念解析及实际运用总结

    流是指传输时的数据,Java为流准备了很多内置类,尤其是IO输入输出流非常常用,这里我们来看一下Java中的stream流的概念解析及实际运用总结
    2016-06-06
  • java对象与json对象间的相互转换的方法

    java对象与json对象间的相互转换的方法

    本篇文章主要介绍了java对象与json对象间的相互转换的方法,详细介绍了json字符串和java对象相互转换,有兴趣的可以了解一下
    2017-01-01
  • 详谈Enumeration接口和Iterator接口的区别

    详谈Enumeration接口和Iterator接口的区别

    下面小编就为大家带来一篇详谈Enumeration接口和Iterator接口的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • java Servlet 实现动态验证码图片示例

    java Servlet 实现动态验证码图片示例

    这篇文章主要介绍了java Servlet 实现动态验证码图片示例的资料,这里整理了详细的代码,有需要的小伙伴可以参考下。
    2017-02-02

最新评论