栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring观察者模式--publishEvent事件发布处理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring观察者模式--publishEvent事件发布处理

Spring发布事件publishEvent 发布-订阅(观察者模式) 一、应用场景

我们一般是在不同的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机械键盘等精美礼品!
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1016945.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号