我们一般是在不同的bean之间进行信息传递,比如我们beanA的事件处理完后,需要beanB进行处理一些业务逻辑的时候这种情况就一般可以使用publishEvent解决。(可以用作日志处理)
二、实现原理ApplicationContext中的事件处理是通过ApplicationEvent类和ApplicationListener接口来提供的,通过ApplicationContext的publishEvent()方法发布到ApplicationListener。
一个事件模型有三个组成部分:被监听对象source(也称为事件源),事件event和监听对象listener。事件发布者在发布事件的时候->通知事件的监听者。
三、事件触发和监听处理过程(1) 使用 org.springframework.context 包下的 ApplicationContext.publishEvent(ApplicationEvent appEvent) 发布事件。
(2) 使用 org.springframework.context.event 包下的 @EventListener(事件名) 监听事件并处理。
注意:
(1) ApplicationContext.publishEvent 默认是同步操作, 并非发布后不管的异步操作,发布事件后需要等 @EventListener 执行完。
(2) 如果需要开启异步操作需要在@EventListener上增加@Async 注解。
1、自定义注解
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperLog {
public String title() default "";
public String content() default "";
}
2、切面类
@Aspect
@Slf4j
@Component
public class OperLogAspect {
@Autowired
private ApplicationContext applicationContext;
// 配置织入点
@Pointcut("@annotation(com.lkl.spring.log.annotation.OperLog)")
public void logPointCut() {
}
@AfterReturning(pointcut = "logPointCut()")
public void doAfterReturning(JoinPoint joinPoint) {
handleLog(joinPoint, null);
}
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
handleLog(joinPoint, e);
}
protected void handleLog(final JoinPoint joinPoint, final Exception e) {
try {
// 获得注解
OperLog controllerLog = getAnnotationLog(joinPoint);
if (controllerLog == null) {
return;
}
// *========数据库日志=========*//
SysOperLog operLog = new SysOperLog();
operLog.setTitle(controllerLog.title());
operLog.setContent(controllerLog.content());
if (e != null) {
//日志异常内容记录
}
// 发布事件
applicationContext.publishEvent(new SysOperLogEvent(operLog));
} catch (Exception exp) {
// 记录本地异常日志
log.error("==前置通知异常==");
log.error("异常信息:{}", exp.getMessage());
exp.printStackTrace();
}
}
private OperLog getAnnotationLog(JoinPoint joinPoint) throws Exception {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null) {
return method.getAnnotation(OperLog.class);
}
return null;
}
}
3、自定义事件(继承ApplicationEvent类)
public class SysOperLogEvent extends ApplicationEvent
{
private static final long serialVersionUID = 8905017895058642111L;
public SysOperLogEvent(SysOperLog source)
{
super(source);
}
}
4.1、自定义监听器(注解方式 @EventListener(监听某个类)),@Async开启异步处理
@Slf4j
@AllArgsConstructor
@Component
public class LogListener {
@Async
@Order
@EventListener(SysOperLogEvent.class)
public void listenOperLog(SysOperLogEvent event) {
SysOperLog sysOperLog = (SysOperLog) event.getSource();
System.out.println("数据库插入操作");
log.info("远程操作日志记录成功:{}", sysOperLog);
}
}
主启动类开启异步操作 @EnableAsync
@EnableAsync
@SpringBootApplication
public class SpringApplyApplication {
public static void main(String[] args) {
SpringApplication.run(SpringApplyApplication.class, args);
}
}
测试如下:
验证成功
4.2、自定义监听器(实现 ApplicationListener接口)
@Slf4j @Component public class LogListenerOther implements ApplicationListener{ @Override public void onApplicationEvent(SysOperLogEvent event) { SysOperLog sysOperLog = (SysOperLog) event.getSource(); System.out.println("数据库插入操作222"); log.info("远程操作日志记录成功222:{}", sysOperLog); } }
验证成功
暑期编程PK赛 得CSDN机械键盘等精美礼品!


