其他分享
首页 > 其他分享> > SpringBoot 事件监听 ApplicationListener

SpringBoot 事件监听 ApplicationListener

作者:互联网

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
	/** 处理一个应用事件*/
	void onApplicationEvent(E event);
}

这里的消息指的是 ApplicationEvent, Spring 提供了ApplicationEvent 类,并内置一些Spring的应用事件,如果需要定义自定义的事件,则需要通过继承 ApplicationEvent实现。


SpringBoot 内置的SpringApplicationEvent如下图所示。


image.png




SpringBoot 的事件发送时具有一定顺序,会按照SpringBoot的启动顺序发送:


image.png
通过继承ApplicationListener<E> 可以实现自定义的事件处理器,下面的代码中展示了监听ApplicationEvent事件的功能

/**
 * 自定义的事件监听器,监听事件为 ApplicationEvent
 */
@Slf4j
@Component
public class CustomerApplicationListener implements ApplicationListener<ApplicationEvent> {
    @Override
    public void onApplicationEvent(ApplicationEvent e) {
        log.info("接收到 Spring事件 => {}", e.getClass().getSimpleName());
    }
}


// 启动应用后,可以在控制台看到应用的相关事件,控制台打印结果如下
 接收到 Spring事件 => ServletWebServerInitial
 接收到 Spring事件 => ContextRefreshedEvent  
 接收到 Spring事件 => ApplicationStartedEvent
 接收到 Spring事件 => AvailabilityChangeEvent
 接收到 Spring事件 => ApplicationReadyEvent  
 接收到 Spring事件 => AvailabilityChangeEvent


事实上,我们也可以通过自定义事件的方式,实现自己的相关的业务逻辑。比如下面的代码中展示了在Spring应用启动完成后会发送一个自定义的消息, 同样的此消息必须继承自ApplicationEvent 下面的代码中定义了CustomerEvent。

@Getter
@Setter
public class OrderPayEvent extends ApplicationEvent {
    private final String content;

    private final Long time;
    
    public MyCustomerEvent(String content) {
        super("自定义的事件源");
        this.content = content;
        this.time = System.currentTimeMillis();
    }
}


在需要的地方使用SpringBoot的上下文 ApplicationContext 发布事件, 那么相应的自定义消息处理器的就会接收到消息。
**

默认情况下,接收事件的发送和处理在同一个线程,但是可以通过 @Async@EnableAsync 启用异步处理。

// 通过SpringBoot上下文发送事件
context.publishEvent(new OrderPayEvent("这是自定义的应用启动完成消息"));

/**
 * 自定义的事件监听器,监听事件为 OrderPayEvent
 *
 * @apiNote 如果需要异步处理能力的话,添加此注解,注意SpringBoot应用需要添加@EnableAsync注解,否则该注解不生效
 */
@Slf4j
@Component
public class CustomerEventListener implements ApplicationListener<OrderPayEvent> {

    @Async
    @Override
    public void onApplicationEvent(OrderPayEvent e) {
        log.info("接收到 自定义的事件 => {}", e.getClass().getSimpleName());
        log.info("事件内容 => {}", e.getContent());
        log.info("接收到消息的线程 ==> {}", Thread.currentThread().getName());
    }
}



// 控制台输出结果
发送消息的线程:main
接收到 自定义的事件 => OrderPayEvent
事件内容 => 这是自定义的应用启动完成消息
接收到消息的线程 ==> task-1


本质上,SpringBoot 通过应用事件广播器ApplicationEventMulticaster 的方式实现事件监听器的注册和管理以及事件的发送 。

public interface ApplicationEventMulticaster {
    
    // 新增事件监听器
	void addApplicationListener(ApplicationListener<?> listener);

	// 新增事件监听器
	void addApplicationListenerBean(String listenerBeanName);

	// 移除事件监听器
	void removeApplicationListener(ApplicationListener<?> listener);

	// 移除事件监听器		
	void removeApplicationListenerBean(String listenerBeanName);

	// 移除全部事件监听器
	void removeAllListeners();

	// 发送应用事件
	void multicastEvent(ApplicationEvent event);

	// 发送应用事件
	void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}


通过查看 ApplicationContext 源码的方式可以看到其publicEvent的源码调用了multicastEvent 方法发送应用事件。

protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
	Assert.notNull(event, "Event must not be null");

	// Decorate event as an ApplicationEvent if necessary
	ApplicationEvent applicationEvent;
	if (event instanceof ApplicationEvent) {
		applicationEvent = (ApplicationEvent) event;
	}
	else {
		applicationEvent = new PayloadApplicationEvent<>(this, event);
		if (eventType == null) {
			eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
		}
	}

	// Multicast right now if possible - or lazily once the multicaster is initialized
	if (this.earlyApplicationEvents != null) {
		this.earlyApplicationEvents.add(applicationEvent);
	}
	else {
        // 此处获取到 ApplicationEventMulticaster 实例后发送消息
		getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
	}

	// Publish event via parent context as well...
	if (this.parent != null) {
		if (this.parent instanceof AbstractApplicationContext) {
			((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
		}
		else {
			this.parent.publishEvent(event);
		}
	}
}

  1. 经典架构设计-消息驱动架构

标签:ApplicationListener,自定义,Spring,ApplicationEvent,event,事件,监听器,监听,SpringBoot
来源: https://blog.csdn.net/qq_20221151/article/details/115329694