简单易用的spring event观察者模式,用于实现业务解耦!

  • Post author:
  • Post category:其他





注:今天分享spring event的原因是我们在自定义log注解使用到了,供大家参考!!!



======


前言:


在实际业务开发过程中会遇到一些与主业务流程没有太大关联性的辅助业务流程,例如服务的

操作日志记录、邮件发送、短信发送

等功能,这些业务与主业务流程

耦合性

较低,并且很多功能都会使用到,使用场景的不同只是描述信息的差异,所以针对这种业务应该降低主业务流程代码

侵入性



同时,在微服务环境,主业务流程存在多个,日志类信息存储和展现的业务可能只存在一个就够用了,我们可以使用MQ实现解耦,但是如果我们引入中间件,又使我们项目比较重,有点大材小用,另一个角度考虑就是事件和响应的问题,我们可以使用观察者模式,但是我们自己代码实现,有增加了工作量和代码复杂度,所以我们在这里使用spring中的一个特性(

spring event

),在实现我们需求的同时,又能避免上述问题;


简介:


Spring Event(Application Event)

其实就是一个

观察者设计模式

,一个 Bean 处理完成任务后希望通知其它 Bean 或者说一个 Bean 想观察监听另一个Bean 的行为。

非常适合用于解耦的场景!!!


使用说明:

1)自定义事件

定义事件,继承 ApplicationEvent 的类成为一个事件类

package com.service;

import lombok.ToString;
import org.springframework.context.ApplicationEvent;



@ToString
public class LogProductEvent extends ApplicationEvent {

    private String username;

    public LogProductEvent(Object source) {
        super(source);
    }

    public LogProductEvent(Object source, String username) {
        super(source);
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

2)自定义监听器

监听并处理事件,使用 @EventListener 注解;

package com.service;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class LogProductListener {

    @SneakyThrows
    @EventListener(LogProductEvent.class)
    public void onApplicationEvent(LogProductEvent event) {
        String username = event.getUsername();
        long start = System.currentTimeMillis();
        Thread.sleep(2000);
        long end = System.currentTimeMillis();
        log.info("-----------------用户:{}:登录耗时:({})毫秒", username, (end - start));
    }
}

3)定义发布者

发布事件,通过 ApplicationEventPublisher 发布事件;

package com.service;


import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class LoginService {


    /** 注入ApplicationContext用来发布事件 */
    private final ApplicationContext applicationContext;

    /**
     * 下单
     *
     * @param username 用户ID
     */
    public String login(String username) {

        long start = System.currentTimeMillis();
        //登录信息校验


        applicationContext.publishEvent(new LogProductEvent(this,username));

        long end = System.currentTimeMillis();
        log.info("--------------------操作完成,耗时:{}毫秒", end - start);
        return "登录成功";
    }

}

4)执行

package com.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


import javax.annotation.PostConstruct;

@Component
public class SpringBootTest {

    @Autowired
    private LoginService loginService;

    @PostConstruct
    public void Test() {
        loginService.login("admin");
    }

}

5)执行结果

[INFO ] 2022-11-11 23:27:35,730 com.service.LogProductListener - -----------------用户:admin:登录耗时:(2009)毫秒
[INFO ] 2022-11-11 23:27:47,641 com.service.LoginService - --------------------操作完成,耗时:2010毫秒



版权声明:本文为weixin_37598243原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。