Spring事件监听器

Spring 事件框架

Spring事件框架包含三个部件:

  • 事件:ApplicationEvent
  • 事件监听器:ApplicationListener,对监听到的事件进行处理
  • 事件发布:ApplicationEventPublisherApplicationContext继承了该接口,在ApplicationContext的抽象实现类AbstractApplicationContext中做了实现

Spring 事件原理

Spring提供的事件类型

img

  • ContextStartedEventApplicationContext启动后触发的事件;
  • ContextStoppedEventApplicationContext停止后触发的事件;
  • ContextRefreshedEventApplicationContext初始化或刷新完成后触发的事件;(容器初始化完成后调用)
  • ContextClosedEventApplicationContext关闭后触发的事件;(如web容器关闭时自动会触发spring容器的关闭)

事件发布者

ApplicationContext接口继承了ApplicationEventPublisher,并在AbstractApplicationContext实现了具体代码,实际执行是委托给ApplicationEventMulticaster

1
2
3
4
5
6
7
8
9
10
// AbstractApplicationContext.class
public void publishEvent(ApplicationEvent event) {
//省略部分代码
}
// 事件发布委托给ApplicationEventMulticaster来执行
getApplicationEventMulticaster().multicastEvent(event);
if (this.parent != null) {
this.parent.publishEvent(event);
}
}

常用的ApplicationContext都继承自AbstractApplicationContext,如ClassPathXmlApplicationContextXmlWebApplicationContext等,自动拥有这个功能

  • ApplicationEventMulticaster 初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// AbstractApplicationContext.class
public void refresh() throws BeansException, IllegalStateException {
// 初始化ApplicationEventMulticaster
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// 注册监听器
registerListeners();
}
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
//先查找BeanFactory中是否有ApplicationEventMulticaster(自定义)
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
}
else {
// 创建默认的SimpleApplicationEventMulticaster
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}

Spring容器初始化的时候会调用initApplicationEventMulticaster()初始化 ApplicationEventMulticaster,如果没有自定义的applicationEventMulticaster则默认创建一个SimpleApplicationEventMulticaster

  • multicastEvent发布事件

其中SimpleApplicationEventMulticaster发布事件的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// SimpleApplicationEventMulticaster.class
public void multicastEvent(final ApplicationEvent event) {
//获得监听器集合,遍历监听器,可支持同步和异步的广播事件
for (final ApplicationListener listener : getApplicationListeners(event)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(new Runnable() {
public void run() {
listener.onApplicationEvent(event);
}
});
}
else {
// 执行监听器逻辑
listener.onApplicationEvent(event);
}
}
}

如果给它一个executor,它就可以异步支持发布事件了。

事件监听器

  • registerListeners注册事件监听器
1
2
3
4
5
6
7
8
9
// AbstractApplicationContext.class
protected void registerListeners() {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String lisName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(lisName);
}
}

Spring使用反射机制,通过方法getBeanNamesForType获取所有实现了ApplicationListener接口的Bean,并调用addApplicationListenerBean方法将其注册到applicationEventMulticaster中。所以可以在Spring配置文件中配置自定义监听器,在Spring初始化的时候,会把监听器自动注册到注册表中去。

  • SmartApplicationListener监听器
1
2
3
4
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
// 处理收到的事件
void onApplicationEvent(E event);
}
1
2
3
4
5
6
7
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
// 如果实现支持该事件类型 那么返回true
boolean supportsEventType(Class<? extends ApplicationEvent> eventType);
// 如果实现支持“目标”类型,那么返回true
boolean supportsSourceType(Class<?> sourceType);
}

该接口可方便实现去判断支持的事件类型、目标类型。

  1. supportsEventType:用于指定支持的事件类型,只有支持的才调用onApplicationEvent
  2. supportsSourceType:支持的目标类型,只有支持的才调用onApplicationEvent

案例

  • 定义事件
1
2
3
4
5
public class TestEvent extends ApplicationEvent {
public TestEvent(String source) {
super(source);
}
}
  • 定义监听器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class TestListener implements SmartApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.out.println("hello: " + event.getSource());
}
// 监听器执行的顺序,值越小优先级越高
@Override
public int getOrder() {
return 1;
}
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return eventType == TestEvent.class;
}
@Override
public boolean supportsSourceType(Class<?> sourceType) {
return sourceType == String.class;
}
}
  • 测试
1
2
3
4
5
6
7
8
9
10
11
12
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring-listener-config.xml" })
public class TestMain {
@Autowired
private ApplicationContext applicationContext;
@Test
public void testPublishEvent() {
applicationContext.publishEvent(new TestEvent("world."));
}
}

参考

Spring的事件与异步事件

Spring ApplicationContext事件机制

详解Spring事件驱动模型

热评文章