0
点赞
收藏
分享

微信扫一扫

09_springboot整合事件监听机制 - SmartApplicationListener

木匠0819 2022-03-11 阅读 85

1 SmartApplicationListener介绍

Spring ApplicationEvent以及对应的Listener提供了一个事件监听、发布订阅的实现,内部实现方式是观察者模式,可以解耦业务系统之间的业务,提供系统的可拓展性、复用性以及可维护性。

Spring 提供的ApplicationEvent & Listener有3种实现方式:本章节使用的方式:SmartApplicationListener的使用方式。
SmartApplicationListener接口继承了ApplicationListener 和 Ordered接口,实现了事件监听和排序的功能。
在这里插入图片描述

public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {

	/**
	 * Determine whether this listener actually supports the given event type(判断这个监听器是否真支持给定的事件类型).
	 * @param eventType the event type (never {@code null})(事件类型)
	 */
	boolean supportsEventType(Class<? extends ApplicationEvent> eventType);

	/**
	 * Determine whether this listener actually supports the given source type(判断这个监听器是否支持给定的源类型).
	 * <p>The default implementation always returns {@code true}.
	 * @param sourceType the source type, or {@code null} if no source
	 */
	default boolean supportsSourceType(@Nullable Class<?> sourceType) {
		return true;
	}

	/**
	 * Determine this listener's order in a set of listeners for the same event(确定此监听器在同一事件的一组监听器中的顺序).
	 * <p>The default implementation returns {@link #LOWEST_PRECEDENCE}.
	 */
	@Override
	default int getOrder() {
		return LOWEST_PRECEDENCE;
	}

	/**
	 * Return an optional identifier for the listener(返回监听器的可选标识符).
	 * <p>The default value is an empty String.
	 * @since 5.3.5
	 * @see EventListener#id
	 * @see ApplicationEventMulticaster#removeApplicationListeners
	 */
	default String getListenerId() {
		return "";
	}
}

2 SmartApplicationListener代码实现

SmartApplicationListener是高级监听器,是ApplicationListener的子类,能够实现有序监听。
假设订单在创建之后(业务层service)需要将订单创建的消息发送通知到Kafka集群做进一步处理,之前的伪代码可能为:

package com.zs.service;
@Service
public class OrderManager {
    /**
     * 模拟创建订单
     */
    public void createOrder() {
        Long orderId = 12345L;
        OrderDTO order = new OrderDTO();
        order.setOrderId(orderId);
        order.setCreateTime(new Date());

        // 2、调用第三方的接口, 去通知订单创建;这样的方式耦合性太高了,不建议采用这种方式。
        // invoke service...

        // 建议使用事件发布机制解耦
        // ...
    }
}

2.1 SmartApplicationListener实现事件发布机制

(1)首先定义事件源对象,对象中包含需要发送的基本信息。

package com.zs.pojo;
@Data
public class OrderDTO {
    private long orderId;
    private Date createTime;
}

(2)定义发生的事件:

package com.zs.event;
public class OrderCreateEvent extends ApplicationEvent {
    @Getter
    private OrderDTO orderDTO;
    /**
     * 重写构造函数
     * @param source    发生事件的源对象
     * @param orderDTO  事件对应的信息
     */
    public OrderCreateEvent(Object source, OrderDTO orderDTO) {
        super(source);
        this.orderDTO = orderDTO;
    }
}

(3)事件发布:

package com.zs.publish;
public interface EventPublishService<T> {
    void publishEvent(T event);
}
package com.zs.publish.impl;
@Service("springEventPublishService")
public class SpringEventPublishServiceImpl implements EventPublishService<ApplicationEvent>, ApplicationContextAware {
    private ApplicationContext applicationContext;
    @Override
    public void publishEvent(ApplicationEvent event) {
        applicationContext.publishEvent(event);
    }
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

(4)事件监听:当有事件发生时,监听到事件的变更通知做进一步处理:

package com.zs.listener;
@Component
public class OrderCreateEventListener implements SmartApplicationListener {
    /**
     * 判断这个监听器是否真支持给定的事件类型
     * @param eventClass
     * @return
     */
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventClass) {
        return eventClass == OrderCreateEvent.class;
    }
    /**
     * 判断这个监听器是否支持给定的源类型
     * @param sourceType
     * @return
     */
    @Override
    public boolean supportsSourceType(@Nullable Class<?> sourceType) {
        return true;
    }
    /**
     * 定义事件监听器的顺序
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        OrderCreateEvent orderCreateEvent = (OrderCreateEvent) applicationEvent;
        OrderDTO orderDTO = orderCreateEvent.getOrderDTO();
        System.out.println("===  收到订单创建事件  ===" + orderDTO);
        // 业务逻辑
        // ......
    }
}

(5)改造:如何使用Spring事件发布机制实现业务解耦:

package com.zs.service;
@Service
public class OrderManager {
    @Autowired
    @Qualifier("springEventPublishService")
    private EventPublishService eventPublishService;
    /**
     * 模拟创建订单
     */
    public void createOrder() {
        Long orderId = 12345L;
        OrderDTO order = new OrderDTO();
        order.setOrderId(orderId);
        order.setCreateTime(new Date());
        // 使用事件发布机制解耦
        eventPublishService.publishEvent(new OrderCreateEvent(this, order));
    }
}

(6)测试:

package com.zs.controller;
@RestController
public class OrderController {
    @Autowired
    private OrderManager orderManager;
    @RequestMapping("/order/create")
    public void createOrder() {
        orderManager.createOrder();
    }
}

上面使用Spring SmartApplicationListener实现的事件驱动模型,使kafka消息发送从订单主流程业务中解耦出来。当然,上述只是个例子,光从例子上看并不能体现应用Spring的事件发布机制的简洁性。这个demo只是为了介绍Spring SmartApplicationListener的使用,在实际应用中可能有更适合用此方法实现业务解耦的场景,如订单状态变更时发送消息就可以使用本文介绍的方法。

3 SmartApplicationListener支持异步使用示例

应用SmartApplicationListener实现的Spring 事件驱动模型可以配合使用Spring提供的@Async注解实现异步调用。@Async的实现是利用配置好的线程池任务ThreadPoolTaskExecutor执行注解所在的方法。

@Configuration
@EnableAsync
public class ListenerAsyncConfiguration implements AsyncConfigurer {

    /**
     * 获取异步线程池执行对象
     * @return
     */
    @Override
    public Executor getAsyncExecutor() {
        //使用Spring内置线程池任务对象
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        //设置线程池参数
        taskExecutor.setCorePoolSize(5);
        taskExecutor.setMaxPoolSize(10);
        taskExecutor.setQueueCapacity(25);
        taskExecutor.initialize();
        return taskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }
}

使用的时候,只要加上@Async注解即可:

@Component
public class OrderEventListener implements SmartApplicationListener {
    @Override
    @Async
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        // 获取注册用户信息
        OrderStatusMsgEvent orderStatusMsgEvent = (OrderStatusMsgEvent) applicationEvent;
        OrderDTO orderInfo = orderStatusMsgEvent.getOrderDTO();
        // 模拟kafka发送
        // kafkaProducer.sendMsg(orderInfo);
        System.out.println("======kafka发送成功====");
    }
}
举报

相关推荐

0 条评论