起源
Spring的Application拥有发布事件并且注册事件监听器的能力,拥有一套完整的事件发布和监听机制。在Java中,通过java.util. EventObject来描述事件,通过java.util. EventListener来描述事件监听器,在众多的框架和组件中,建立一套事件机制通常是基于这两个接口来进行扩展。
概念
- ApplicationEvent就是Spring的事件接口
- ApplicationListener就是Spring的事件监听器接口,所有的监听器都实现该接口
- ApplicationEventPublisher是Spring的事件发布接口,ApplicationContext实现了该接口
- ApplicationEventMulticaster就是Spring事件机制中的事件广播器,默认实现SimpleApplicationEventMulticaster
在Spring中通常是ApplicationContext本身担任监听器注册表的角色,在其子类AbstractApplicationContext中就聚合了事件广播器ApplicationEventMulticaster和事件监听器ApplicationListnener,并且提供注册监听器的addApplicationListnener方法。
执行流程
当一个事件源产生事件时,它通过事件发布器ApplicationEventPublisher发布事件,然后事件广播器ApplicationEventMulticaster会去事件注册表ApplicationContext中找到事件监听器ApplicationListnener,并且逐个执行监听器的onApplicationEvent方法,从而完成事件监听器的逻辑。
默认启动事件
- ApplicationStartedEvent
- ApplicationEnvironmentPreparedEvent
- ApplicationPreparedEvent
- ApplicationFailedEvent
源码片段
AbstractApplicationContext实现了ApplicationEventPublisher接口方法,通过ApplicationEventMulticaster广播事件
public void publishEvent(ApplicationEvent event) {
Assert.notNull(event, "Event must not be null");
if(this.logger.isTraceEnabled()) {
this.logger.trace("Publishing event in " + this.getDisplayName() + ": " + event);
}
this.getApplicationEventMulticaster().multicastEvent(event);
if(this.parent != null) {
this.parent.publishEvent(event);
}
}
spring boot 系统事件分发
EventPublishingRunListener中通过initialMulticaster广播事件
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Object analyzers = null;
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
try {
DefaultApplicationArguments ex = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, ex);
Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext();
new FailureAnalyzers(context);
this.prepareContext(context, environment, listeners, ex, printedBanner);
this.refreshContext(context);
this.afterRefresh(context, ex);
listeners.finished(context, (Throwable)null);
stopWatch.stop();
if(this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);
throw new IllegalStateException(var9);
}
}
EventPublishingRunListener 以starting为例,发布ApplicationStartedEvent启动事件
public void starting() {
this.initialMulticaster.multicastEvent(new ApplicationStartedEvent(this.application, this.args));
}
SimpleApplicationEventMulticaster
public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
ResolvableType type = eventType != null?eventType:this.resolveDefaultEventType(event);
Iterator var4 = this.getApplicationListeners(event, type).iterator();
while(var4.hasNext()) {
final ApplicationListener listener = (ApplicationListener)var4.next();
Executor executor = this.getTaskExecutor();
if(executor != null) {
executor.execute(new Runnable() {
public void run() {
SimpleApplicationEventMulticaster.this.invokeListener(listener, event);
}
});
} else {
this.invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
ErrorHandler errorHandler = this.getErrorHandler();
if(errorHandler != null) {
try {
listener.onApplicationEvent(event);
} catch (Throwable var7) {
errorHandler.handleError(var7);
}
} else {
try {
listener.onApplicationEvent(event);
} catch (ClassCastException var8) {
String msg = var8.getMessage();
if(msg != null && !msg.startsWith(event.getClass().getName())) {
throw var8;
}
Log logger = LogFactory.getLog(this.getClass());
if(logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, var8);
}
}
}
}
参考
http://liuxiamai.iteye.com/blog/2322197
http://blog.csdn.net/nution/article/details/72765813
http://blog.csdn.net/chszs/article/details/49097919
|