1、是什么?

SpringBoot事件机制是指SpringBoot中的开发人员可以通过编写自定义事件来对应用程序进行事件处理。我们可以创建自己的事件类,并在应用程序中注册这些事件,当事件被触发时,可以对其进行处理。在SpringBoot中,事件可以是任意类型的,可以是基于Spring的事件,也可以是自定义的事件。事件处理可以是在应用程序中特定的方法中进行,也可以是通过Spring提供的事件处理API进行处理。

主要有三大对象:

  • 1、事件源 :具体的事件内容
  • 2、事件发布者 :发布事件
  • 3、事件监听者 :监听事件

9大事件触发顺序&时机

1、ApplicationStartingEvent:应用启动但未做任何事情, 除过注册listeners and initializers.

2、ApplicationEnvironmentPreparedEvent: Environment 准备好,但context 未创建.

3、ApplicationContextInitializedEvent: ApplicationContext 准备好,ApplicationContextInitializers 调用,但是任何bean未加载

4、ApplicationPreparedEvent: 容器刷新之前,bean定义信息加载

5、ApplicationStartedEvent: 容器刷新完成, runner未调用

=以下就开始插入了探针机制====

6、AvailabilityChangeEvent: LivenessState.CORRECT应用存活; 存活探针

7、ApplicationReadyEvent: 任何runner被调用

8、AvailabilityChangeEvent:ReadinessState.ACCEPTING_TRAFFIC就绪探针,可以接请求

9、ApplicationFailedEvent :启动出错

2、怎么玩?

这样把,我们先模拟一个场景:现在有一个用户打卡的需求,用户登录进行签到打卡,打卡会奖励一些积分;当连续打卡次数到了7次我们就送一张优惠券。当然除了前面的操作我们还需要记录一下用户的登录日志

明确一下:

  • 1、加积分
  • 2、送优惠券
  • 3、记录登录日志

常规写法如下:

@Autowired
private AccountService accountService; @Autowired
private CouponService couponService; @Autowired
private SystemService systemService; @GetMapping("/login")
public String login(@RequestParam String username,
@RequestParam String password) {
// 伪代码
// login...... // 加积分
accountService.addAccountScore(username); // 送优惠券
couponService.addCoupon(username); // 记录登录日志
systemService.addLoginLog(username); // 等等....
return "success";
}

问题:上面的代码实现功能是没问题的,但是如果我还需要做其他的操作岂不是每次都得修改代码加功能了...,这不是我们想要的,也不符合【开闭原则】;下面我们就用时间解耦上面的代码

(1) 定义一个事件发布器
package com.ly.event;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service; /**
* 事件发布器
*
* @author ly (个人博客:https://www.cnblogs.com/ybbit)
* @date 2023-06-26 20:06
* @tags 喜欢就去努力的争取
*/
@Service
public class EventPublisher implements ApplicationEventPublisherAware { ApplicationEventPublisher applicationEventPublisher; /**
* 发送所有事件
*
* @param event
*/
public void sendEvent(ApplicationEvent event) {
// 真正的发送事件
this.applicationEventPublisher.publishEvent(event);
} /**
* 会被自动调用,把真正发事件的底层组件给我们注入进来
*
* @param applicationEventPublisher
*/
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
}
(2) 定义一个事件
package com.ly.event;

import com.ly.entity.UserEventEntity;
import org.springframework.context.ApplicationEvent; /**
* 事件
*
* @author ly (个人博客:https://www.cnblogs.com/ybbit)
* @date 2023-06-26 20:06
* @tags 喜欢就去努力的争取
*/
public class LoginSuccessEvent extends ApplicationEvent {
public LoginSuccessEvent(UserEventEntity source) {
super(source);
}
}
(3) 定义一个事件对象
package com.ly.entity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor; /**
* @author ly (个人博客:https://www.cnblogs.com/ybbit)
* @date 2023-06-26 20:05
* @tags 喜欢就去努力的争取
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class UserEventEntity { private String username; private String password; }
(4) 编写相关逻辑(伪代码)

AccountService

package com.ly.service;

import com.ly.entity.UserEventEntity;
import com.ly.event.LoginSuccessEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Service; /**
* 记录积分
*
* @author ly (个人博客:https://www.cnblogs.com/ybbit)
* @date 2023-06-26 20:23
* @tags 喜欢就去努力的争取
*/
@Service
public class AccountService implements ApplicationListener<LoginSuccessEvent> { public void addAccountScore(String username) {
System.out.println(username + "增加积分");
} @Override
public void onApplicationEvent(LoginSuccessEvent event) {
UserEventEntity userEventEntity = (UserEventEntity) event.getSource();
System.out.println("============AccountService=============onApplicationEvent");
addAccountScore(userEventEntity.getUsername());
}
}

CouponService

package com.ly.service;

import com.ly.entity.UserEventEntity;
import com.ly.event.LoginSuccessEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service; /**
* 优惠券
*
* @author ly (个人博客:https://www.cnblogs.com/ybbit)
* @date 2023-06-26 20:23
* @tags 喜欢就去努力的争取
*/
@Service
public class CouponService { @EventListener
public void onEnvet(LoginSuccessEvent event) {
// TODO 判断逻辑......
UserEventEntity userEventEntity = (UserEventEntity) event.getSource();
System.out.println("=========CouponService========= onEnvet");
addCoupon(userEventEntity.getUsername());
} public void addCoupon(String username) {
System.out.println(username + "发送优惠券");
} }

SystemService

package com.ly.service;

import com.ly.entity.UserEventEntity;
import com.ly.event.LoginSuccessEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service; /**
* 登录日志
*
* @author ly (个人博客:https://www.cnblogs.com/ybbit)
* @date 2023-06-26 20:23
* @tags 喜欢就去努力的争取
*/
@Service
public class SystemService { @Order(1)
@EventListener
public void onEvent(LoginSuccessEvent event) {
System.out.println("==========SystemService========= onEvent");
UserEventEntity userEventEntity = (UserEventEntity) event.getSource();
addLoginLog(userEventEntity.getUsername());
} public void addLoginLog(String username) {
System.out.println(username + "记录登录日志");
}
}
(5) 修改旧的登录处理逻辑
@Autowired
private EventPublisher eventPublisher; @Autowired
private AccountService accountService; @Autowired
private CouponService couponService; @Autowired
private SystemService systemService; @GetMapping("/login")
public String login(@RequestParam String username,
@RequestParam String password) {
/* // 伪代码
// login...... // 加积分
accountService.addAccountScore(username); // 送优惠券
couponService.addCoupon(username); // 记录登录日志
systemService.addLoginLog(username); // 等等....*/ // 我们发送登录事件就好了
eventPublisher.sendEvent(new LoginSuccessEvent(new UserEventEntity(username, password))); return "success";
}

3、事件监听的几种方式

1、在应用上下文直接添加

2、使用spring.factories文件

3、使用@EventListener注解

4、自定义监听器实现ApplicationListener接口并交给Spring管理

事件发布:ApplicationEventPublisherAware 或注入:ApplicationEventMulticaster

事件监听:组件 + @EventListener

SpringBoot事件机制的更多相关文章

  1. [译]谈谈SpringBoot 事件机制

    要"监听"事件,我们总是可以将"监听器"作为事件源中的另一个方法写入事件,但这将使事件源与监听器的逻辑紧密耦合. 对于实际事件,我们比直接方法调用更灵活.我们可 ...

  2. springBoot的事件机制---GenericApplicationListener用法

    springBoot的事件机制---GenericApplicationListener用法 什么是ApplicationContext? 它是Spring的核心,Context我们通常解释为上下文环 ...

  3. SpringBoot事件监听机制及观察者模式/发布订阅模式

    目录 本篇要点 什么是观察者模式? 发布订阅模式是什么? Spring事件监听机制概述 SpringBoot事件监听 定义注册事件 注解方式 @EventListener定义监听器 实现Applica ...

  4. ApplicationEvent事件机制源码分析

    <spring扩展点之三:Spring 的监听事件 ApplicationListener 和 ApplicationEvent 用法,在spring启动后做些事情> <服务网关zu ...

  5. SpringBoot学习(二)探究Springboot启动机制

    引言: SpringBoot为我们做的自动配置,确实方便快捷,但是对于新手来说,如果不大懂SpringBoot内部启动原理,以后难免会吃亏.所以这次博主就跟你们一起探究一下SpringBoot的启动原 ...

  6. 搞清楚Spring事件机制后:Spring的源码看起来简单多了

    本文主讲Spring的事件机制,意图说清楚: 什么是观察者模式? 自己实现事件驱动编程,对标Spring的事件机制 彻底搞懂Spring中的事件机制,从而让大家 本文内容较长,代码干货较多,建议收藏后 ...

  7. 观察者模式之spring事件机制

    ddsspring中的事件机制使用到设计模式中的观察者模式 ,观察者模式有两个概念,1.观察者.被观察者.2.被观察者做出相应得动作,观察者能接收到.不分析设计模式,学习下spring中的事件机制实际 ...

  8. 【移动端兼容问题研究】javascript事件机制详解(涉及移动兼容)

    前言 这篇博客有点长,如果你是高手请您读一读,能对其中的一些误点提出来,以免我误人子弟,并且帮助我提高 如果你是javascript菜鸟,建议您好好读一读,真的理解下来会有不一样的收获 在下才疏学浅, ...

  9. tkinter事件机制

    一.tkinter.Event tkinter的事件机制跟js是一样的,也是只有一个Event类,这个类包罗万象,集成了键盘事件,鼠标事件,包含各种参数. 不像java swing那种强类型事件,sw ...

  10. [解惑]JavaScript事件机制

    群里童鞋问到关于事件传播的一个问题:“事件捕获的时候,阻止冒泡,事件到达目标之后,还会冒泡吗?”. 初学 JS 的童鞋经常会有诸多疑问,我在很多 QQ 群也混了好几年了,耳濡目染也也收获了不少,以后会 ...

随机推荐

  1. Redis从入门到放弃(11):雪崩、击穿、穿透

    1.前言 Redis作为一款高性能的缓存数据库,为许多应用提供了快速的数据访问和存储能力.然而,在使用Redis时,我们不可避免地会面对一些常见的问题,如缓存雪崩.缓存穿透和缓存击穿.本文将深入探讨这 ...

  2. 如何调用API接口获取淘宝商品数据

    淘宝商品数据的获取是一项非常重要的技术,它可以为淘宝卖家和买家提供有利的数据分析和扩展市场的机会.调用API接口是一种快速.方便.高效的方式获取淘宝商品数据. 以下是一些步骤来调用API接口来获取淘宝 ...

  3. Elasticsearch之环境搭建

    一.安装 elasticsearch -- 拉取镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:8.9.1 -- 创建 doc ...

  4. 《Python魔法大冒险》004 第一个魔法程序

    在图书馆的一个安静的角落,魔法师和小鱼坐在一张巨大的桌子前.桌子上摆放着那台神秘的笔记本电脑. 魔法师: 小鱼,你已经学会了如何安装魔法解释器和代码编辑器.是时候开始编写你的第一个Python魔法程序 ...

  5. 【krpano】KRPano测试开发专用浏览器

    KRPano技术解密网站:http://www.krpano.tech 在开发KRPano项目时候,每次测试时均需要打开测试服务器,或者上传到空间中才能进行测试,十分不方便. 因此本站提供了免费的KR ...

  6. Shell 文件或目录操作符(-e、-d、-f、-r、-w、-x)

    操作符 操作符 含义-e 判断对象是否存在(Exist),若存在则结果为真-d 判断对象是否为目录(Directory),是则为真-f 判断对象是否为一般文件(File),是则为真-r 判断对象是否有 ...

  7. 记一次 .NET某账本软件 非托管泄露分析

    一:背景 1. 讲故事 中秋国庆长假结束,哈哈,在老家拍了很多的短视频,有兴趣的可以上B站观看:https://space.bilibili.com/409524162 ,今天继续给大家分享各种奇奇怪 ...

  8. 什么是 CSS?

    1.什么是 CSS? CSS 指的是层叠样式表* (Cascading Style Sheets) CSS 描述了如何在屏幕.纸张或其他媒体上显示 HTML 元素 CSS 节省了大量工作.它可以同时控 ...

  9. CF1190C Tokitsukaze and Duel

    搬运一下本喵的 lg 博客 qwq 详细讲一下如何判定后手能否获胜,对其他题解做个补充.(蒟蒻的我想了好久来着 此题的关键点在于可以重复上一个人的操作使局面保持不变. 考虑先手的获胜条件,由上一段可知 ...

  10. Quartus 入门

    转载请标明出处:https://www.cnblogs.com/leedsgarden/p/17790320.html 本文介绍的是Quartus的免费版,可以满足基本的教学需要 如果你用的是Xili ...