应用启动过程生命周期事件感知(9大事件)、应用运行中事件感知(无数种)
- 事件发布:
ApplicationEventPublisherAware
或注入:ApplicationEventMulticaster
- 事件监听:
组件 + @EventListener
场景:
当用户登录后,我们需要为用户增加一个积分、随机获取一张优惠券、增加日志等,传统的开发模式为在用户登录的login()方法后调用积分、优惠券、日志服务。这样在后续的开发中login()方法可能会频繁变动,根据设计模式方法应该对新增开放,修改关闭,所以可以在login()方法中发布登录成功的事件,在积分、优惠券、日志服务增加对事件的监听进行后续处理即可。
编写代码
LoginController.java
在login()方法后发布登录成功事件
package com.atguigu.boot3.core.controller;
import com.atguigu.boot3.core.entity.UserEntity;
import com.atguigu.boot3.core.event.EventPublisher;
import com.atguigu.boot3.core.event.LoginSuccessEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* @date 2023/10/30 18:57
*/
@RestController
public class LoginController {
@Autowired
EventPublisher eventPublisher;
@GetMapping("/login")
public String login(@RequestParam("username") String username,
@RequestParam("passwd")String passwd){
//业务处理登录
System.out.println("业务处理登录完成....");
//1、创建事件信息
LoginSuccessEvent event = new LoginSuccessEvent(new UserEntity(username, passwd));
//2、发送事件
eventPublisher.publishEvent(event);
//设计模式:对新增开放,对修改关闭
return username+"登录成功";
}
}
LoginSuccessEvent.java
事件定义
通过继承ApplicationEvent类,将source传给父类对象。
package com.atguigu.boot3.core.event;
import com.atguigu.boot3.core.entity.UserEntity;
import org.springframework.context.ApplicationEvent;
/**
* 登录成功事件
* @author 朱俊伟
* @date 2023/10/30 18:56
*/
public class LoginSuccessEvent extends ApplicationEvent {
/**
* @param source 代表是谁登录成了
*/
public LoginSuccessEvent(UserEntity source) {
super(source);
}
}
EventPublisher.java
事件发布器
定义事件发布器,实现
ApplicationEventPublisherAware接口
,用来发布事件
package com.atguigu.boot3.core.event;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Component;
/**
* @date 2023/10/30 18:58
*/
@Component
public class EventPublisher implements ApplicationEventPublisherAware {
/**
* 底层发送事件用的组件,SpringBoot会通过ApplicationEventPublisherAware接口自动注入给我们
* 事件是广播出去的。所有监听这个事件的监听器都可以收到
*/
ApplicationEventPublisher applicationEventPublisher;
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.applicationEventPublisher = applicationEventPublisher;
}
/**
* 发布事件
* @param event 事件
*/
public void publishEvent(LoginSuccessEvent event) {
applicationEventPublisher.publishEvent(event);
}
}
CouponService.java
优惠券服务
可以通过给方法定义
@EventListener
注解,代表该类监听某种事件
可以给监听器使用@Order(1)
注解定义监听器的顺序,数字越小,越先执行
package com.atguigu.boot3.core.service;
import com.atguigu.boot3.core.entity.UserEntity;
import com.atguigu.boot3.core.event.LoginSuccessEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
/**
* 优惠券服务
* @date 2023/10/30 19:06
*/
@Service
@Slf4j
public class CouponService {
@Order(1)
@EventListener
public void onEvent(LoginSuccessEvent loginSuccessEvent){
log.info("CouponService.onEvent....");
UserEntity user = (UserEntity) loginSuccessEvent.getSource();
sendCoupon(user);
}
public void sendCoupon(String username){
System.out.println(username + " 随机得到了一张优惠券");
}
public void sendCoupon(UserEntity user){
sendCoupon(user.getUsername());
}
}
AccountService.java
积分服务
可以实现
ApplicationListener
接口来监听事件
实现onApplicationEvent
方法来进行事件的处理
package com.atguigu.boot3.core.service;
import com.atguigu.boot3.core.entity.UserEntity;
import com.atguigu.boot3.core.event.LoginSuccessEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
/**
* 积分服务
* @date 2023/10/30 19:03
*/
@Service
@Slf4j
@Order(2)
public class AccountService implements ApplicationListener<LoginSuccessEvent> {
@Override
public void onApplicationEvent(LoginSuccessEvent event) {
log.info("AccountService.onApplicationEvent.....");
UserEntity user = (UserEntity) event.getSource();
addAccountScore(user);
}
public void addAccountScore(UserEntity user){
System.out.println(user.getUsername() +" 加了1分");
}
}
SysService.java
日志服务
package com.atguigu.boot3.core.service;
import com.atguigu.boot3.core.entity.UserEntity;
import com.atguigu.boot3.core.event.LoginSuccessEvent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
/**
* 日志服务
* @date 2023/10/30 19:09
*/
@Service
@Slf4j
public class SysService {
@EventListener
@Order(3)
public void onEvent(LoginSuccessEvent event){
log.info("SysService.onEvent....");
UserEntity user = (UserEntity) event.getSource();
recordLog(user);
}
public void recordLog(UserEntity user){
System.out.println(user.getUsername() + "登录信息已被记录");
}
}
UserEntity.java
实体类
package com.atguigu.boot3.core.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @date 2023/10/30 18:55
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class UserEntity {
private String username;
private String passwd;
}
调用
http://localhost:8080/login?username=admin&passwd=123
控制台打印结果
业务处理登录完成....
2023-10-30T19:20:11.670+08:00 INFO 11984 --- [nio-8080-exec-5] c.a.boot3.core.service.CouponService : CouponService.onEvent....
admin 随机得到了一张优惠券
2023-10-30T19:20:11.671+08:00 INFO 11984 --- [nio-8080-exec-5] c.a.boot3.core.service.AccountService : AccountService.onApplicationEvent.....
admin 加了1分
2023-10-30T19:20:11.671+08:00 INFO 11984 --- [nio-8080-exec-5] c.atguigu.boot3.core.service.SysService : SysService.onEvent....
admin登录信息已被记录
在业务类中增加方法来实现对事件的监听个人感觉是比较好的方法,可以更好的调节事件处理的顺序以及减少业务类对实现接口的定义。
参考:
https://www.yuque.com/leifengyang/springboot3/lliphvul8b19pqxp#Cq1vD
标签:core,SpringBoot,boot3,事件驱动,开发,springframework,atguigu,import,event From: https://www.cnblogs.com/zjw-blog/p/17798650.html