Spring Boot使用ApplicationEvent和Listener快速实现业务解耦

ApplicationEvent简介

ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业务逻辑之间的解耦,提高可扩展性以及可维护性。

通过 ApplicationEvent 类和 ApplicationListener 接口来提供在 ApplicationContext 中处理事件。如果一个 bean 实现 ApplicationListener,那么每次 ApplicationEvent 被发布到 ApplicationContext 上,那个 bean 会被通知。

Spring内置以下标准事件:

  • ContextRefreshedEvent

ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext 接口中使用 refresh() 方法来发生。

  • ContextStartedEvent

当使用 ConfigurableApplicationContext 接口中的 start() 方法启动 ApplicationContext 时,该事件被发布。你可以调查你的数据库,或者你可以在接受到这个事件后重启任何停止的应用程序。

  • ContextStoppedEvent

当使用 ConfigurableApplicationContext 接口中的 stop() 方法停止 ApplicationContext 时,发布这个事件。你可以在接受到这个事件后做必要的清理的工作。

  • ContextClosedEvent

当使用 ConfigurableApplicationContext 接口中的 close() 方法关闭 ApplicationContext 时,该事件被发布。一个已关闭的上下文到达生命周期末端;它不能被刷新或重启。

  • RequestHandledEvent

这是一个 web-specific 事件,告诉所有 bean HTTP 请求已经被服务。

构建Model

@Data
@NoArgsConstructor
public class User {
    private String name;
    private String email;
}

创建Event事件

首先注意:listener都是围绕着event来挂起的

public class UserRegisterEvent extends ApplicationEvent {
    @Getter @Setter
    public User user;

    /**
     *
     * @param source 发生事件的对象
     * @param user 注册用户对象
     */
    public UserRegisterEvent(Object source,User user) {
        super(source);
        this.user = user;
    }
}

事件发布

此部分主要在业务逻辑模块触发,主要用到ApplicationContext类以及它的publishEvent(ApplicationEvent t)方法

@Slf4j
@Service
public class UserService {
    @Autowired
    private ApplicationContext applicationContext;

    public void register(User user){
        //省略业务逻辑
        //发布UserRegisterEvent事件
        log.info("-------- 发布UserRegisterEvent事件 --------");
        applicationContext.publishEvent(new UserRegisterEvent(this, user));
    }
}

测试用例

@Test
public void publishEvent() {
    User user = new User();
    user.setName("Joe.Ye");
    user.setEmail("test@test.com");
    userService.register(user);
}

创建Event事件监听

基于@EventListener注解实现

注解方式比较简单,并不需要实现任何接口

/**
 * 注解方式比较简单,并不需要实现任何接口,排序随机
 */
@Component
public class AnnotationRegisterListener {

    @EventListener
    public void sendEmail(UserRegisterEvent userRegisterEvent) {
        //获取注册用户对象
        User user = userRegisterEvent.getUser();
        //输出注册用户信息
        System.out.println("AnnotationRegisterListener: 发送邮件, 用户名: " + user.getName()+", 邮箱: " + user.getEmail());
    }

    /**
     * 注册监听实现方法
     * @param userRegisterEvent 用户注册事件
     */
    @EventListener
    public void register(UserRegisterEvent userRegisterEvent) {
        //获取注册用户对象
        User user = userRegisterEvent.getUser();
        //输出注册用户信息
        System.out.println("AnnotationRegisterListener: 注册信息, 用户名: " + user.getName() + ", 邮箱: " + user.getEmail());
    }
}

实现 ApplicationListener接口

这种方式也是Spring之前比较常用的监听事件方式,在实现ApplicationListener接口时需要将监听事件作为泛型参数传递

@Component
public class RegisterListener implements ApplicationListener<UserRegisterEvent> {

    @Override
    public void onApplicationEvent(UserRegisterEvent userRegisterEvent) {
        //获取注册用户对象
        User user = userRegisterEvent.getUser();
        //输出注册用户信息
        System.out.println("RegisterListener: 注册信息, 用户名: " + user.getName()+", 密码: " + user.getEmail());
    }

}

实现SmartApplicationListener接口

可以实现有序监听

@Component
public class SmartRegisterListener implements SmartApplicationListener {

    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) {
        //只有UserRegisterEvent监听类型才会执行下面逻辑
        return aClass == UserRegisterEvent.class;
    }

    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        //只有在UserService内发布的UserRegisterEvent事件时才会执行下面逻辑
        return sourceType == UserService.class;
    }

    /**
     * supportsEventType & supportsSourceType 两个方法返回true时调用该方法执行业务逻辑
     * @param applicationEvent applicationEvent 具体监听实例,这里是UserRegisterEvent
     */
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        //转换事件类型
        UserRegisterEvent userRegisterEvent = (UserRegisterEvent) applicationEvent;
        //获取注册用户对象信息
        User user = userRegisterEvent.getUser();
        //完成注册业务逻辑
        System.out.println("SmartRegisterListener: " + user.getName());
    }

    /**
     * return 的数值越小证明优先级越高,执行顺序越靠前
     * @return
     */
    @Override
    public int getOrder() {
        return 10;
    }
}

SmartApplicationListener接口继承了全局监听ApplicationListener,并且泛型对象使用的ApplicationEvent来作为全局监听,可以理解为使用SmartApplicationListener作为监听父接口的实现,监听所有事件发布。

可以看到除了上面的方法,还提供了一个getOrder方法,这个方法就可以解决执行监听的顺序问题,return的数值越小证明优先级越高,执行顺序越靠前。

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/09/spring-boot-use-application-event-and-listener-to-quickly-achieve-business-decoupling/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
Spring Boot使用ApplicationEvent和Listener快速实现业务解耦
ApplicationEvent简介 ApplicationEvent以及Listener是Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式,设计初衷也是为了系统业……
<<上一篇
下一篇>>
文章目录
关闭
目 录