首页 > 其他分享 >SpringBoot事件机制

SpringBoot事件机制

时间:2023-06-26 21:56:31浏览次数:45  
标签:username SpringBoot event 事件 import 机制 com public ly

1、是什么?

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

主要有三大对象:

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

image

image

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";
}

image

3、事件监听的几种方式

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

2、使用spring.factories文件
image

3、使用@EventListener注解
image

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

事件发布:ApplicationEventPublisherAware 或注入:ApplicationEventMulticaster
事件监听:组件 + @EventListener

标签:username,SpringBoot,event,事件,import,机制,com,public,ly
From: https://www.cnblogs.com/ybbit/p/17506794.html

相关文章

  • 【Azure 事件中心】Kafka 生产者发送消息失败,根据失败消息询问机器人得到的分析步骤
    问题描述AzureEventHubs--Kafka生产者发送消息存在延迟接收和丢失问题,在客户端的日志中发现如下异常:2023-06-0502:00:20.467[kafka-producer-thread|producer-1]ERRORcom.deloitte.common.kafka.CommonKafkaProducer-messageId:9235f334-e39f-b429-227e-45cd30dd6486......
  • SpringBoot04
    1.Springboot和Mybatis的整合1.1.使用注解的方式整合MyBatis引入相关的依赖<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><!--mybatis起步依赖--><dependency>......
  • 【Azure 事件中心】Kafka 生产者发送消息失败的分析步骤
    问题描述AzureEventHubs--Kafka生产者发送消息存在延迟接收和丢失问题,在客户端的日志中发现如下异常:2023-06-0502:00:20.467[kafka-producer-thread|producer-1]ERRORcom.deloitte.common.kafka.CommonKafkaProducer-messageId:9235f334-e39f-b429-227e-45cd30dd......
  • JQ 合成事件
    style.css*{margin:0;padding:0;} body{font-size:13px;line-height:130%;padding:60px}#panel{width:300px;border:1pxsolid#0050D0}.head{padding:5px;background:#96E555;cursor:pointer}.content{padding:10px;text-indent:2em;border-......
  • JQ 事件对象的属性
    demo.html<html><head><title>event.type</title><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/><scriptsrc="js/jquery-1.10.1.min.js"type="text/javascript">......
  • JQ 移除事件
    demo.html<html><head><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/><title></title><styletype="text/css">*{margin:0;padding:0;} body{font-size:13px;line-hei......
  • JQ 其它的点击事件用法
    demo.html<html><head><title></title><metahttp-equiv="Content-Type"content="text/html;charset=utf-8"/><style>.over{ color:red; background:#888;}</style><scriptsrc="js/j......
  • SpringBoot自动配置原理
    SpringBoot自动配置自动配置是SpringBoot的核心因素,SpringBoot在整合每一种第三方技术时,都离不开自动配置。但在了解自动配置之前,Spring容器如何进行对bean的加载以及加载控制也是一个非常重要的前提知识。1.bean的加载方式1.1方式一:配置文件+<bean/>标签最初级的bean的加载......
  • springboot 跨域设置
      写文章 SpringBoot项目解决跨域的几种方案小满只想睡觉一直快乐!​关注她  在用SpringBoot开发后端服务时,我们一般是提供接口给前端使用,但前端通过浏览器调我们接口时,浏览器会有个同源策略的限制,即协议,域名,端口任一不一样时都会......
  • Visual Basic(简称VB)是一种编程语言,由微软公司开发。它是基于事件驱动的编程语言,主要用
    VisualBasic(简称VB)是一种编程语言,由微软公司开发。它是基于事件驱动的编程语言,主要用于Windows操作系统上的应用程序开发。在VisualBasic中,可以使用图形用户界面(GUI)来创建各种应用程序,包括桌面应用程序、数据库应用程序、Web应用程序等。VisualBasic提供了许多现成的控件和工......