srpingboot web - 启动(3) 监听器
2021-06-04 10:02
标签:task 启动失败 == 环境 env try png 准备 could not 在run() 方法中调用了 getRunListeners(args) 方法, 先看一下这个方法干了什么 加载配置 spring.factories 中的配置, 然后创建配置中的 EventPublishingRunListener , 封装到 SpringApplicationRunListeners 类中的 this.listeners 属性中. 1. 这里创建了一个多播器: SimpleApplicationEventMulticaster
2. 将容器中10个监听器放入多播器中. 上一篇提到过, 容器中加载了10个监听器, 放在 this.listeners 属性中. 这里的顺序与配置的读取顺序不同, 是经过排序过的. 此处的 this.listeners 中的 this -> SpringApplicationRunListeners . 所以调用的是 EventPublishingRunListener的starting() 方法. 看一下 multicastEvent 方法: 1. 判断监听器是否为 GenericApplicationListener 类型 |-> 如果是, 则调用其 supportsEventType() 和 supportsSourceType() , 且同时满足, 才可以. 否则会被过滤掉 |-> 如果不是, 则 使用GenericApplicationListenerAdapter 进行适配转换, 然后 调用上面两个方法, 同时满足, 才可以. 否则会被过滤掉 满足条件的有4个监听器: 此处看一下 LoggingApplicationListener 的两个方法执行: 1. supportsEventType() 可以看到, 这里他支持5中类型, 其中正好就有当前发布的 ApplicationStartingEvent 事件. 2. supportsSourceType() 这里就是调用 监听器的 onApplicationEvent 方法, 并传入要多波的事件. 这里仍然来看 LoggingApplicationListener 的 onApplicationEvent 方法: 不同的事件进来, 执行不同的方法. srpingboot web - 启动(3) 监听器 标签:task 启动失败 == 环境 env try png 准备 could not 原文地址:https://www.cnblogs.com/elvinle/p/12341900.html接上一篇
一. getRunListeners()
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class>[] types = new Class>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=org.springframework.boot.context.event.EventPublishingRunListener
1. 创建 EventPublishingRunListener
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
this.initialMulticaster = new SimpleApplicationEventMulticaster();
for (ApplicationListener> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
addApplicationListener()
@Override
public void addApplicationListener(ApplicationListener> listener) {
synchronized (this.retrievalMutex) {
// Explicitly remove target for a proxy, if registered already,
// in order to avoid double invocations of the same listener.
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
this.defaultRetriever.applicationListeners.add(listener);
this.retrieverCache.clear();
}
}
ListenerRetriever 是 AbstractApplicationEventMulticaster 的一个内部类. 所以监听器是放在 一个内部类的 applicationListeners 属性中:
public final Set
二. listeners.starting()
public void starting() {
for (SpringApplicationRunListener listener : this.listeners) {
listener.starting();
}
}
//EventPublishingRunListener.java
@Override
public void starting() {
//创建Application的启动事件, 并进行多波
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}//SimpleApplicationEventMulticaster.java
@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));
// getApplicationListeners 会对监听器进行过滤
for (final ApplicationListener> listener : getApplicationListeners(event, type)) {
//获取线程池, 暂时为null
Executor executor = getTaskExecutor();
if (executor != null) {
//异步发送事件
executor.execute(() -> invokeListener(listener, event));
}
else {
//同步发送事件
invokeListener(listener, event);
}
}
}getApplicationListeners()
protected boolean supportsEvent(
ApplicationListener> listener, ResolvableType eventType, @Nullable Class> sourceType) {
GenericApplicationListener smartListener = (listener instanceof GenericApplicationListener ?
(GenericApplicationListener) listener : new GenericApplicationListenerAdapter(listener));
return (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType));
}
private static final Class>[] EVENT_TYPES = { ApplicationStartingEvent.class,
ApplicationEnvironmentPreparedEvent.class, ApplicationPreparedEvent.class,
ContextClosedEvent.class, ApplicationFailedEvent.class };
@Override
public boolean supportsEventType(ResolvableType resolvableType) {
return isAssignableFrom(resolvableType.getRawClass(), EVENT_TYPES);
}
@Override
public boolean supportsSourceType(Class> sourceType) {
return isAssignableFrom(sourceType, SOURCE_TYPES);
}
private boolean isAssignableFrom(Class> type, Class>... supportedTypes) {
if (type != null) {
for (Class> supportedType : supportedTypes) {
if (supportedType.isAssignableFrom(type)) {
return true;
}
}
}
return false;
}
private static final Class>[] SOURCE_TYPES = { SpringApplication.class,
ApplicationContext.class };
@Override
public boolean supportsSourceType(Class> sourceType) {
//这里调用的还是上面的那个方法, 只是传入参数不同
return isAssignableFrom(sourceType, SOURCE_TYPES);
}invokeListener()
protected void invokeListener(ApplicationListener> listener, ApplicationEvent event) {
//不管 errorhandler 是否为null, 都会调用 doInvokeListener 方法
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().getName())) {
// 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;
}
}
}@Override
public void onApplicationEvent(ApplicationEvent event) {
//Application启动
if (event instanceof ApplicationStartingEvent) {
onApplicationStartingEvent((ApplicationStartingEvent) event);
}
//环境准备完成
else if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationEnvironmentPreparedEvent(
(ApplicationEnvironmentPreparedEvent) event);
}
//Application 准备完
else if (event instanceof ApplicationPreparedEvent) {
onApplicationPreparedEvent((ApplicationPreparedEvent) event);
}
//容器关闭
else if (event instanceof ContextClosedEvent && ((ContextClosedEvent) event)
.getApplicationContext().getParent() == null) {
onContextClosedEvent();
}
//Application启动失败
else if (event instanceof ApplicationFailedEvent) {
onApplicationFailedEvent();
}
}
文章标题:srpingboot web - 启动(3) 监听器
文章链接:http://soscw.com/index.php/essay/90343.html