参考版本:2.0.8.RELEASE
启动方法run中运行监听器的启动
查找 jar包中META-INF/spring.factories中SpringApplicationRunListener的定义,如果只引入了springbootstarter包的话,这里只定义了一个监听器EventPublishingRunListener
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListenerSpringApplicationRunListeners listeners = getRunListeners(args); listeners.starting();
SpringApplicationRunListeners:这个类是SpringApplicationRunListener的一个集合
public void starting() { for (SpringApplicationRunListener listener : this.listeners) { listener.starting(); } }
下面来看EventPublishingRunListener的starting方法
EventPublishingRunListener:继承了SpringApplicationRunListener,使用初始化好的事件广播器广播Application启动事件,这个类的接口实现主要有initialMulticaster来完成---装饰器模式
@Override public void starting() { this.initialMulticaster.multicastEvent( new ApplicationStartingEvent(this.application, this.args)); }
接下来看是如果广播事件的:spring中的事件监控--观察者模式
SimpleApplicationEventMulticaster:是接口ApplicationEventMulticaster的一个简单实现类,将所有的事件广播给所有的监听器,每个监听器只关心自己要监听的事件,不关心的就会忽略。默认在调用(当前)的线程中调用监听器,如果定义了线程池就会在新的线程中调用。
@Override public void multicastEvent(ApplicationEvent event) { multicastEvent(event, resolveDefaultEventType(event)); } @Override 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(); if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); } } }
从代码getApplicationListeners(event, type)的结果来看,有以下四种监听器都监听了ApplicationStartingEvent,接下来每种监听器逐个执行
/** * Invoke the given listener with the given event. * @param listener the ApplicationListener to invoke * @param event the current event to propagate * @since 4.1 */ protected void invokeListener(ApplicationListener> listener, ApplicationEvent event) { ErrorHandler errorHandler = getErrorHandler(); if (errorHandler != null) { try { doInvokeListener(listener, event); } catch (Throwable err) { errorHandler.handleError(err); } } else { doInvokeListener(listener, event); } }
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) { try { listener.onApplicationEvent(event);//这句是重点啦,要到具体对应的监听器中查看 } catch (ClassCastException ex) { String msg = ex.getMessage(); if (msg == null || matchesClassCastMessage(msg, event.getClass())) { // Possibly a lambda-defined listener which we could not resolve the generic event type for // -> let's suppress the exception and just log a debug message. Log logger = LogFactory.getLog(getClass()); if (logger.isDebugEnabled()) { logger.debug("Non-matching event type for listener: " + listener, ex); } } else { throw ex; } } }
接下来一个个看每个监听器在监听事件发生后都做了哪些事情 :
1、DelegatingApplicationListener:委派监听器,委派给那些在环境属性context.listener.classes指定的那些监听器。
@Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ApplicationEnvironmentPreparedEvent) { List> delegates = getListeners( ((ApplicationEnvironmentPreparedEvent) event).getEnvironment()); if (delegates.isEmpty()) { return; } this.multicaster = new SimpleApplicationEventMulticaster(); for (ApplicationListener listener : delegates) { this.multicaster.addApplicationListener(listener); } } if (this.multicaster != null) { this.multicaster.multicastEvent(event); } }
2、LiquibaseServiceLocatorApplicationListener
3、BackgroundPreinitializer:对于一些耗时的任务使用一个后台线程尽早触发它们开始执行初始化,这是Springboot的缺省行为。这些初始化动作也可以叫做预初始化。 设置系统属性spring.backgroundpreinitializer.ignore为true可以禁用该机制。 该机制被禁用时,相应的初始化任务会发生在前台线程。
看看都做了哪些初始化任务:
// 记录预初始化任务是否已经在执行,初始值设置为false,表示未开始
private static final AtomicBoolean preinitializationStarted = new AtomicBoolean(
false);// 记录预初始化任务是否已经完成,1表示未完成,0表示完成
private static final CountDownLatch preinitializationComplete = new CountDownLatch(1);@Override public void onApplicationEvent(SpringApplicationEvent event) { if (event instanceof ApplicationStartingEvent && preinitializationStarted.compareAndSet(false, true)) { //如果当前事件是ApplicationStartingEvent,并且预初始化任务尚未执行 // 则 :将preinitializationStarted设置为预初始化任务开始执行; // 开始执行预初始化任务; performPreinitialization(); } if ((event instanceof ApplicationReadyEvent || event instanceof ApplicationFailedEvent) && preinitializationStarted.get()) { try { preinitializationComplete.await(); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } } private void performPreinitialization() { try { Thread thread = new Thread(new Runnable() { @Override public void run() { runSafely(new ConversionServiceInitializer()); runSafely(new ValidationInitializer()); runSafely(new MessageConverterInitializer()); runSafely(new MBeanFactoryInitializer()); runSafely(new JacksonInitializer()); runSafely(new CharsetInitializer()); preinitializationComplete.countDown(); } public void runSafely(Runnable runnable) { try { runnable.run(); } catch (Throwable ex) { // Ignore } } }, "background-preinit"); thread.start(); } catch (Exception ex) { // This will fail on GAE where creating threads is prohibited. We can safely // continue but startup will be slightly slower as the initialization will now // happen on the main thread. preinitializationComplete.countDown(); } }
4、LoggingApplicationListener:配置日志系统。如果有logging.config配置文件,就使用它启动日志系统,如果没有就使用默认配置。
@Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ApplicationStartingEvent) { onApplicationStartingEvent((ApplicationStartingEvent) event); } else if (event instanceof ApplicationEnvironmentPreparedEvent) { onApplicationEnvironmentPreparedEvent( (ApplicationEnvironmentPreparedEvent) event); } else if (event instanceof ApplicationPreparedEvent) { onApplicationPreparedEvent((ApplicationPreparedEvent) event); } else if (event instanceof ContextClosedEvent && ((ContextClosedEvent) event) .getApplicationContext().getParent() == null) { onContextClosedEvent(); } else if (event instanceof ApplicationFailedEvent) { onApplicationFailedEvent(); } }
本文通过查看监听器启动方法了解到springboot的一些内置监听器的作用,有一篇博客写的非常详细可参考:Springboot内置ApplicationListener