Spring内置事件和自定义事件
事件传递对象(ApplicationEvent)
ApplicationEvent
是事件接口,继承自EventObject
(Java规范要求事件对象都需要继承该类)。
内置事件对象包括两部分:
ApplicationContextEvent
是Spring Framework需要的。SpringApplicationEvent
该类在Spring boot包下。
事件监听(ApplicationListener)
ApplicationListener
是Spring的事件监听接口,实现了jdk中的EventListener
,该接口只提供了一个抽象方法void onApplicationEvent(E event)
用于处理接收到的事件。
子接口SmartApplicationListener
增加了两个抽象方法(supportsEventType
,supportsSourceType
)并且还继承了Ordered
接口提供监听器排序。
supportsEventType
和supportsSourceType
两个方法都是过滤方法返回事件类型和事件源类型是否支持。
事件发布
ApplicationEventPublisher
ApplicationEventPublisher
事件发布接口,ApplicationContext
接口继承了该接口,这也就说明Spring Framework的核心IoC
容器都具有发布事件的能力,接口方法在AbstractApplicationContext
中实现,来看一下实现代码:
/** |
从代码中可以看出事件发布实际上是委派给ApplicationEventMulticaster
实例来做的,下面我们来看ApplicationEventMulticaster
。
ApplicationEventMulticaster
ApplicationEventMulticaster
接口有一个抽象实现和一个简单实现,通过查看ApplicationEventMulticaster
接口规范我们会发现改接口提供注册Listener
和通知Listener
的接口契约。
Spring内部的事件发布是通过ApplicationEvent#publishEvent
再委派给ApplicationEventMulticaster
实际去发送事件的。我们来看一下ApplicationEventMulticaster
的实现逻辑。
ApplicationEventMulticaster
的实例化/**
* 初始化ApplicationEventMulticaster.
* 如果在IoC容器上下文中不存在以applicationEventMulticaster命名的ApplicationEventMulticaster Bean
* 就使用新创建一个SimpleApplicationEventMulticaster,并注册到IoC容器中。
*
* Initialize the ApplicationEventMulticaster.
* Uses SimpleApplicationEventMulticaster if none defined in the context.
* @see org.springframework.context.event.SimpleApplicationEventMulticaster
*/
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
} else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}SimpleApplicationEventMulticaster#multicastEvent()
的实现
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
//如果Executor如果不为空,那么将调用Executor的execute方法,发起异步通知
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
//否则同步通知
else {
invokeListener(listener, event);
}
}
}从代码中可以看出,只要Executor不为空,通知将异步执行,否则同步执行通知,所以我们可以传递Executor对象让通知异步执行。
SpringBoot方式
public class MulticasterAsyncConfig {
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(100);
executor.setQueueCapacity(2000);
return executor;
}
public ApplicationEventMulticaster applicationEventMulticaster(BeanFactory beanFactory) {
SimpleApplicationEventMulticaster multicaster = new SimpleApplicationEventMulticaster(beanFactory);
multicaster.setTaskExecutor(threadPoolTaskExecutor());
return multicaster;
}
}
Spring XML方式
<task:executor id="executor" pool-size="10" />
<!-- 名字必须是applicationEventMulticaster和messageSource是一样的,默认找这个名字的对象 -->
<!-- 名字必须是applicationEventMulticaster,因为AbstractApplicationContext默认找个 -->
<!-- 如果找不到就new一个,但不是异步调用而是同步调用 -->
<bean id="applicationEventMulticaster" class="org.springframework.context.event.SimpleApplicationEventMulticaster">
<!-- 注入任务执行器 这样就实现了异步调用(缺点是全局的,要么全部异步,要么全部同步(删除这个属性即是同步)) -->
<property name="taskExecutor" ref="executor"/>
</bean>但是这种方式有个弊端就是通知要么是全部是同步要么全部是异步,不能根据需要决定是否异步,所以我们使用另一种方式实现通知消息异步。我们会在下一篇自定义事件中讲解
自定义事件
有了Spring的支持我们自定义事件是非常简单的。
自定义事件
public class CustomEvent<T> extends ApplicationEvent {
public CustomEvent(T source) {
super(source);
}
}自定义事件监听继承自
ApplicationListener
public class CustomEventListener implements ApplicationListener<CustomEvent> {
public void onApplicationEvent(CustomEvent customEvent) {
System.out.println("得到事件内容:" + customEvent.getSource());
}
}自定义事件监听实现
SmartApplicationListener
CustomSmartEventListener1
order=1
public class CustomSmartEventListener1 implements SmartApplicationListener {
public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) {
return StringUtils.equals(aClass.getName(),CustomEvent.class.getName());
}
public boolean supportsSourceType(Class<?> aClass) {
return StringUtils.equals(String.class.getName(),aClass.getName());
}
public void onApplicationEvent(ApplicationEvent applicationEvent) {
System.out.println("接收到通知1:" + applicationEvent.getSource());
}
public int getOrder() {
return 1;
}
}CustomSmartEventListener2
order=2
public class CustomSmartEventListener2 implements SmartApplicationListener {
public boolean supportsEventType(Class<? extends ApplicationEvent> aClass) {
return StringUtils.equals(aClass.getName(),CustomEvent.class.getName());
}
public boolean supportsSourceType(Class<?> aClass) {
return StringUtils.equals(String.class.getName(),aClass.getName());
}
public void onApplicationEvent(ApplicationEvent applicationEvent) {
System.out.println("接收到通知2:" + applicationEvent.getSource());
}
public int getOrder() {
return 2;
}
}事件发布
private ApplicationContext applicationContext;
"/") (
public String index(){
applicationContext.publishEvent(new CustomEvent<>("收到消息了吗?"));
return "/index";
}输出结果:
得到事件内容:收到消息了吗?
接收到通知1:收到消息了吗?
接收到通知2:收到消息了吗?从输出接口可以看到order越小监听器越早被调用。