spring事件监听机制Event 详解

spring事件监听机制Event 详解

一、事件监听的由来

Spring的事件(Application Event)为Bean和Bean之间的消息同步提供了支持。当一个Bean处理完成一个任务之后,希望另外一个Bean知道并能做相应的处理,这时我们就需要让另外一个Bean监听当前Bean所发生的事件

二、如何实现事件

  • 我们可以自定义一个事件,继承spring提供的ApplicationEvent
  • 定义一个监听器,需要实现 ApplicationListener,监听我们定义的事件
  • 使用容器发布事件 applicationContext.publishEvent(ApplicationEvent event)

三、通过实现ApplicationListener同步监听事件

我们可以先自己定义一个事件SpringTestEvent

package com.zeng.spring.event;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.event.SpringApplicationEvent;
import org.springframework.context.ApplicationEvent;

public class SpringTestEvent extends ApplicationEvent {


  /**
   * Create a new {@code ApplicationEvent}.
   *
   * @param source the object on which the event initially occurred or with
   *               which the event is associated (never {@code null})
   */
  public SpringTestEvent(String source) {
    super(source);
  }
}

然后定义一个事件监听器,一般我们是在这里做逻辑处理

package com.zeng.spring.listener;

import com.zeng.spring.event.SpringTestEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class SpringTestListener implements ApplicationListener<SpringTestEvent> {
  @Override
  public void onApplicationEvent(SpringTestEvent event) {
    Object source = event.getSource();
    System.out.println("SpringTestListener接收到了消息 : "+source);
  }
}

使用 ApplicationContext 进行事件的发布

package com.zeng.spring.controller;

import com.zeng.spring.event.SpringTestEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test")

public class TestDemo {

  @Autowired
  private ApplicationContext applicationContext;

  @GetMapping("/send")
  public void sendTestEvent() {

    applicationContext.publishEvent(new SpringTestEvent("helloWord"));
  }
}

测试结果发现消息已经接收成功了

在这里插入图片描述

四、注解的方式实现同步事件监听

我们只需要通过@EventListener这个注解就可以实现

package com.zeng.spring.listener;

import com.zeng.spring.event.SpringTestEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component
public class SpringTestListener01 {
  @EventListener(value = SpringTestEvent.class)
  public void event(SpringTestEvent springTestEvent) {
    System.out.println("SpringTestEvent01接收到的消息"+springTestEvent.getSource());
  }
}

可以看到结果了,以及成功监听了消息

在这里插入图片描述

五、如何实现异步监听

什么事同步监听呢,举个列子就比如我们洗澡和烧水,同步的意思就是我们必须洗完澡才能进行烧水的,在spring事件发布中,就必须等我们的监听器监听完成代码才可以往下执行。我们可以验证一下。我们可以在消息监听者中设置一个沉睡时间。

package com.zeng.spring.listener;

import com.zeng.spring.event.SpringTestEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

@Component
public class SpringTestListener implements ApplicationListener<SpringTestEvent> {
  @Override
  public void onApplicationEvent(SpringTestEvent event) {
    Object source = event.getSource();
    System.out.println("SpringTestListener接收到了消息 : "+source);
    try {
      Thread.sleep(1000);
    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    }
  }
}

你会发现每次都是等SpringTestListener时间监听器中的代码执行完,代码才会继续往下走流程。每次的结果都是SpringTestListener先完成,针对一些场景这样就比较消耗性能了。所以spring还提供了一个异步的方式。

在这里插入图片描述

如何实现呢?我们需要再启动类中添加上@EnableAsync注解开启异步

package com.zeng.spring;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication
@EnableAsync

public class DemoApplication {


  public static void main(String[] args) {
    SpringApplication.run(DemoApplication.class, args);
  }
}

然后再监听者中添加@Async注解,我们给这里加上一个沉睡时间

package com.zeng.spring.listener;

import com.zeng.spring.event.SpringTestEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Component
@Async
public class SpringTestListener implements ApplicationListener<SpringTestEvent> {
  @Override
  public void onApplicationEvent(SpringTestEvent event) {
    Object source = event.getSource();

    try {
      Thread.sleep(10000);
    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    }
    System.out.println("SpringTestListener接收到了消息 : "+source);
  }
}

结果发现我们发布时间后代码先执行了。这样就实现了我们异步监听。

在这里插入图片描述

六、使用场景

Spring Event 的好处在于,通过事件的发布和监听机制,能够将不同业务之间的耦合度降到最低,这些业务之间并不是直接的调用关系,而是通过事件这种松耦合的方式进行交互,这样业务之间的耦合度就会变得更加灵活和可扩展。

  • 可用于收集日志
  • 对外api的调用
  • 发送邮件信息等
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

久★伴i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值