详解SpringBoot 发布ApplicationEventPublisher和监听ApplicationEvent事件

 更新时间:2019年06月10日 11:46:58   作者:miskss  
这篇文章主要介绍了详解SpringBoot 发布ApplicationEventPublisher和监听ApplicationEvent事件,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

资料地址

Spring @Aync

实现方法

  1. 自定义需要发布的事件类,需要继承ApplicationEvent类或PayloadApplicationEvent<T>(该类也仅仅是对ApplicationEvent的一层封装)
  2. 使用@EventListener来监听事件
  3. 使用ApplicationEventPublisher来发布自定义事件(@Autowired注入即可)
/**
 * 自定义保存事件
 * @author peter
 * 2019/1/27 14:59
 */
public class PersonSaveEvent<DATA> extends ApplicationEvent {
  private DATA data;

  public PersonSaveEvent(DATA source) {
    super(source);
    this.data = source;
  }

  public DATA getData() {
    return data;
  }
}

//发布事件
public void savePerson(Person person){
  personDao.save(person);
  publisher.publishEvent(new PersonSaveEvent<>(1));
}
//监听事件
@EventListener
public void listenEvent(PersonSaveEvent<Integer> event) {
   System.out.println("监听到PersonSaveEvent事件; 接收到的值:" + event.getData() + ";发布的时间为" + Instant.ofEpochMilli(event.getTimestamp()));
}

好处

可以使核心业务与子业务进行解耦,也方便后期的业务的扩展。如新用户注册之后,需要发放优惠券,此时可以在保存用户之后,发布一个新用户的注册成功事件,通过监听该事件来实现发放优惠券的功能。后期新增一个对新用户进行xxx功能,此时可以新写一个监听注册成功事件的监听器,来处理新的业务逻辑,而不需要修改之前的注册逻辑。

注意事项

1、监听器方法中一定要try-catch异常,否则会造成发布事件(有事物的)的方法进行回滚
2、可以使用@Order注解来控制多个监听器的执行顺序,@Order传入的值越小,执行顺序越高
3、对于需要进行事物监听或不想try-catch runtime异常,可以使用@TransactionalEventListener注解

@TransactionalEventListener 监听器

在该注解的源码中:

 * <p>If the event is not published within the boundaries of a managed transaction, the
 * event is discarded unless the {@link #fallbackExecution} flag is explicitly set. If a
 * transaction is running, the event is processed according to its {@code TransactionPhase}.

大意是:如果事件的发布不是在事物(@Transactional)范围内,则监听不到该事件,除非将fallbackExecution标志设置为true(@TransactionalEventListener(fallbackExecution = true));如果在事物中,可以选择在事物的哪个阶段来监听事件,默认在事物提交后监听。

修改监听事物的范围:@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)

在监听器中重新开一个事物

 @TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
  public void listenEvent1(PersonSaveEvent<Integer> event) {
    divide(event);
  }
  @Transactional(propagation = Propagation.REQUIRES_NEW)
  public void divide(PersonSaveEvent<Integer> event) {
    System.out.println("监听到PersonSaveEvent事件; 接收到的值:" + event.getData() + ";接受的时间为" + Instant.ofEpochMilli(event.getTimestamp()));
  }

以上事件都是同步,如果需要异步则需要开启异步支持,在监听器方法加上@Async 注解即可。

/**
 * @author peter
 * @version 1.0
 * @date 2019/04/18 08:47
 */
@Configuration
@EnableAsync
public class AsyncEventConfiguration implements AsyncConfigurer {
  @Override
  public Executor getAsyncExecutor() {
    return Executors.newCachedThreadPool();
  }
}

一旦开始异步执行,方法的异常将不会抛出,只能在方法内部处理。如需在方法外处理异常:Async 异常处理在文章最后

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java并发编程之线程池实现原理详解

    Java并发编程之线程池实现原理详解

    池化思想是一种空间换时间的思想,期望使用预先创建好的对象来减少频繁创建对象的性能开销,java中有多种池化思想的应用,例如:数据库连接池、线程池等,下面就来具体讲讲
    2023-05-05
  • 教你如何正确了解java三大特性!!!!

    教你如何正确了解java三大特性!!!!

    所有的面向对象编程语言的思路都是差不多的,而这三大特性,则是思路中的支柱点,接下来我就重点讲解了一下java三大特性,感兴趣的朋友跟随脚本之家小编一起看看吧
    2021-07-07
  • mybatis plus自动生成代码tinyint(1)自动转换为Boolean的问题及解决

    mybatis plus自动生成代码tinyint(1)自动转换为Boolean的问题及解决

    这篇文章主要介绍了mybatis plus自动生成代码tinyint(1)自动转换为Boolean的问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • SpringBoot中忽略实体类中的某个属性不返回给前端的方法(示例详解)

    SpringBoot中忽略实体类中的某个属性不返回给前端的方法(示例详解)

    本文介绍了在Spring Boot中使用Jackson和Fastjson忽略实体类属性不返回给前端的方法,在Jackson中,同时使用@JsonProperty和@JsonIgnore时,@JsonIgnore可能失效,Fastjson中可以使用@JSONField(serialize=false)来实现,本文结合实例代码介绍的非常详细,需要的朋友参考下吧
    2024-11-11
  • Java中Stream流Map分组方式详细汇总

    Java中Stream流Map分组方式详细汇总

    Stream将要处理的元素集合看作一种流,在流的过程中借助Stream API对流中的元素进行操作,比如筛选、排序、聚合等,下面这篇文章主要给大家介绍了关于Java中Stream流Map分组方式的相关资料,需要的朋友可以参考下
    2024-01-01
  • 使用XSD校验Mybatis的SqlMapper配置文件的方法(1)

    使用XSD校验Mybatis的SqlMapper配置文件的方法(1)

    这篇文章以前面对SqlSessionFactoryBean的重构为基础,简单的介绍了相关操作知识,然后在给大家分享使用XSD校验Mybatis的SqlMapper配置文件的方法,感兴趣的朋友参考下吧
    2016-11-11
  • 基于线程池的工作原理与源码解读

    基于线程池的工作原理与源码解读

    下面小编就为大家分享一篇基于线程池的工作原理与源码解读,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • jsch中ChannelShell与ChannelExec的区别及说明

    jsch中ChannelShell与ChannelExec的区别及说明

    这篇文章主要介绍了jsch中ChannelShell与ChannelExec的区别及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • 如何读取properties或yml文件数据并匹配

    如何读取properties或yml文件数据并匹配

    这篇文章主要介绍了如何读取properties或yml文件数据并匹配方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • 一文搞懂hashCode()和equals()方法的原理

    一文搞懂hashCode()和equals()方法的原理

    这篇文章主要介绍了详解hashCode()和equals()的本质区别和联系,本文先对两种方法作了介绍,然后对二者联系进行分析,具有一定参考价值,需要的朋友可以了解下
    2020-06-06

最新评论