事件、监听器在我们开发中会经常遇到,比如某个业务逻辑后需要通知另一个组件去执行相应的逻辑,那就可以使用事件和监听,具体的场景:服务 A 在处理完某个逻辑之后,需要通知服务 B 去处理另一个逻辑,或者服务 A 处理完某个逻辑之后,需要将数据同步到微服务 B。

这种场景就可以自定义事件以及监听器来监听,一旦监听到微服务 A 中的某事件发生,就去通知微服务 B 处理对应的逻辑。

一、spring中的事件监听

spring boot监听屏幕 spring 监听事件_监听器

 Spring 通过 ApplicationEvent 类和 ApplicationListener 接口提供 ApplicationContext 中的事件处理。如果将实现 ApplicationListener 接口的 bean 部署到上下文中,则每次将 ApplicationEvent 发布到 ApplicationContext 时,都会通知该 bean。

简单来说主要分为以下几个部分:

  1. 注册事件
  2. 注册监听器
  3. 发布事件

二、spring中事件监听的使用

事件类:(继承ApplicationEvent即可)

@ToString
public class MyEvent extends ApplicationEvent {

    private String message;

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

监听类:(实现ApplicationListener 或者 使用@EventListener注解)

public class MyListener implements ApplicationListener<MyEvent> {

    @Override
    public void onApplicationEvent(MyEvent event) {
        Console.log("实现ApplicationListener接口监听到的事件信息:{}", event);
    }
}

public class MyAnnotationListener {

    @EventListener
    public void onApplicationEvent(MyEvent event) {
        Console.log("@EventListener注解监听到的事件信息:{}", event);
    }
}

以bean的方式注入Spring容器: 

@Configuration
public class EventConfig {

    @Bean
    public MyListener getMyListener(){
        return new MyListener();
    }

    @Bean
    public MyAnnotationListener getMyAnnotationListener(){
        return new MyAnnotationListener();
    }
}

测试:

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(EventConfig.class);
        context.refresh();
        MyEvent myEvent = new MyEvent(context, "我是事件!");
        context.publishEvent(myEvent);
    }
}
@EventListener注解监听到的事件信息:MyEvent(message=我是事件!)
实现ApplicationListener接口监听到的事件信息:MyEvent(message=我是事件!)

可以看到,在接口调用发布事件时,监听器就会做出相应的操作。且两种监听器都能监测到同一事件。

三、案例

@ToString
@Setter
@Getter
@AllArgsConstructor
public class Goods {

    private String name;

    private String price;
}
@Getter
public class MyEvent extends ApplicationEvent {

    private Goods goods;

    public MyEvent(Object source, Goods goods) {
        super(source);
        this.goods = goods;
    }
}
@Component
public class MyListener implements ApplicationListener<MyEvent> {

    @Override
    public void onApplicationEvent(MyEvent event) {
        Goods goods = event.getGoods();
        Console.log("商品信息:{}", goods);
    }
}
@Service
public class GoodsService {

    @Resource
    private ApplicationContext applicationContext;

    /**
     * 发布事件
     * @return
     */
    public Goods getGoods() {
        Goods goods = new Goods("电视", "6666");
        MyEvent event = new MyEvent(this, goods);
        applicationContext.publishEvent(event);
        return goods;
    }
}
@RestController
public class EventController {

    @Autowired
    GoodsService goodsService;

    @GetMapping("/user")
    public Goods getUser(HttpServletRequest request){
        ServletContext application = request.getServletContext();
        Goods goods = goodsService.getGoods();
        return goods;
    }
}
商品信息:Goods(name=电视, price=6666)

四、Spring框架中有哪些不同类型的事件?

除了上面介绍的通过扩展ApplicationEvent 类来开发自定义事件,Spring 还提供了以下5种标准的事件:

  1. 上下文更新事件(ContextRefreshedEvent):该事件会在ApplicationContext被初始化或者更新时发布。也可以在调用ConfigurableApplicationContext 接口中的refresh()方法时被触发。 
  2. 上下文开始事件(ContextStartedEvent):当容器调用ConfigurableApplicationContext的Start()方法开始/重新开始容器时触发该事件。
  3. 上下文停止事件(ContextStoppedEvent):当容器调用ConfigurableApplicationContext的Stop()方法停止容器时触发该事件。
  4. 上下文关闭事件(ContextClosedEvent):当ApplicationContext被关闭时触发该事件。容器被关闭时,其管理的所有单例Bean都被销毁。
  5. 请求处理事件(RequestHandledEvent):在Web应用中,当一个HTTP请求(Request)结束时触发该事件。