springboot启动源码解析(三):初始化启动上下文、初始化监听器列表、发布开始启动事件

此章节主要对springboot启动过程中,发生的【初始化启动上下文】、【初始化监听器列表】、【发布springboot开始启动事件】进行源码解析,对应的代码如图1所示:

图1:

// 首先初始化一个计时器,并开始计时
StopWatch stopWatch = new StopWatch();
stopWatch.start();
// 初始化启动上下文
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 设置系统参数:java.awt.headless(在系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式,例如Linux服务器)
configureHeadlessProperty();
// 初始化监听器列表
SpringApplicationRunListeners listeners = getRunListeners(args);
// 发布springboot开始启动事件
listeners.starting(bootstrapContext, this.mainApplicationClass);

 


初始化启动上下文

图2:

private DefaultBootstrapContext createBootstrapContext() {
	DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
	this.bootstrappers.forEach((initializer) -> initializer.intitialize(bootstrapContext));
	return bootstrapContext;
}

点击进入【createBootstrapContext()】方法,可以看到首先获取了一个DefaultBootstrapContext类实例 -> bootstrapContext,然后遍历this.bootstrappersbootstrapContext进行初始化,由于this.bootstrappers中无任何元素(见springboot启动源码解析(一):SpringApplication初始化),故对bootstrapContext未执行任何操作,最后将bootstrapContext返回。


设置系统参数:java.awt.headless

图3:

private void configureHeadlessProperty() {
	System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
			System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}

在系统可能缺少显示设备、键盘或鼠标这些外设的情况下可以使用该模式,例如Linux服务器


初始化监听器列表

图4:

private SpringApplicationRunListeners getRunListeners(String[] args) {
	Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
	return new SpringApplicationRunListeners(logger,
			getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
			this.applicationStartup);
}

如图4所示,在【getRunListeners】方法中,一共进行了3步操作:

1、获取了一个class数组types

其中的元素分别为:SpringApplication和String数组的class对象,types主要用于在后序反射初始化对象时,获取到目标的构造方法。

2、获取SpringApplicationRunListener实例对象。

【getSpringFactoriesInstances】方法的目的为:获取并维护SpringApplicationRunListener接口的子类对象列表。在后续的启动过程中,交由listeners发布的事件,实际上是遍历其内部管理的SpringApplicationRunListener对象列表进行发布的。

最终通过getSpringFactoriesInstances获取到的SpringApplicationRunListener类型的对象有且仅有一个:EventPublishingRunListener实例对象。

实例化EventPublishingRunListener对象时,在它的构造方法中(图5)对成员变量进行了一些初始化操作。例如向initialMulticaster中加入了application中维护的9个监听器对象(application监听器的由来详见:springboot启动源码解析(一):SpringApplication初始化),它们分别为:EnvironmentPostProcessorApplicationListener、AnsiOutputApplicationListener、LoggingApplicationListener、BackgroundPreinitializer、DelegatingApplicationListener、ParentContextCloserApplicationListener、ClearCachesApplicationListener、FileEncodingApplicationListener、LiquibaseServiceLocatorApplicationListener

图5(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);
	}
}

3、通过获取到的SpringApplicationRunListener实例,创建一个SpringApplicationRunListeners对象并返回。

注:getSpringFactoriesInstances解析请见:springboot启动源码解析(一):SpringApplication初始化

 


发布springboot开始启动事件

图6:

void starting(ConfigurableBootstrapContext bootstrapContext, Class<?> mainApplicationClass) {
	doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
			(step) -> {
				if (mainApplicationClass != null) {
					step.tag("mainApplicationClass", mainApplicationClass.getName());
				}
			});
}

private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction, Consumer<StartupStep> stepAction) {
	StartupStep step = this.applicationStartup.start(stepName);
	this.listeners.forEach(listenerAction);
	if (stepAction != null) {
		stepAction.accept(step);
	}
	step.end();
}

初始化启动上下文和监听器后,通过调用监听器中的starting方法发布【springboot开始启动】事件,在starting方法中,实际通过调用doWithListeners方法对事件进行发布。

解析doWithListeners方法:

1、初始化一个StartupStep实例,并命名为"spring.boot.application.starting",其作用为:追踪“执行时间”或其他指标。

2、对内部维护的监听器列表进行遍历,执行传入的listenerAction。由于listeners中只包含一个EventPublishingRunListener对象,故此处是用EventPublishingRunListener实例对象执行starting(bootstrapContext)方法。

图7(EventPublishingRunListener的starting方法):

public void starting(ConfigurableBootstrapContext bootstrapContext) {
	this.initialMulticaster
			.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
}

在EventPublishingRunListener的starting方法中,实际上是调用了其成员变量initialMulticaster的multicastEvent(ApplicationEvent event)方法。

图8:

public void multicastEvent(ApplicationEvent event) {
	multicastEvent(event, resolveDefaultEventType(event));
}

/**
 * 解析事件类型
 */
private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
	return ResolvableType.forInstance(event);
}

/**
 * 批量消费事件
 */
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
	ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
	Executor executor = getTaskExecutor();
        // 遍历符合事件的监听器,向这些监听器发布事件
	for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
		if (executor != null) {
			executor.execute(() -> invokeListener(listener, event));
		}
		else {
			invokeListener(listener, event);
		}
	}
}

接下来进入initialMulticaster.multicastEvent(ApplicationEvent event)进行查看。

如图8所示,在 multicastEvent(final ApplicationEvent event, ResolvableType eventType)方法中:

1、调用 getApplicationListeners(event, type)能够在initialMulticaster维护的监听器列表中找到匹配该事件的监听器列表

此处符合ApplicationStartingEvent事件的监听器有:LoggingApplicationListener、BackgroundPreinitializer、DelegatingApplicationListener、LiquibaseServiceLocatorApplicationListener

2、对符合要求的监听器进行遍历,执行invokeListener(listener, event)方法

图9:(向监听器发布事件)

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()) ||
				(event instanceof PayloadApplicationEvent &&
						matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
			Log loggerToUse = this.lazyLogger;
			if (loggerToUse == null) {
				loggerToUse = LogFactory.getLog(getClass());
				this.lazyLogger = loggerToUse;
			}
			if (loggerToUse.isTraceEnabled()) {
				loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
			}
		}
		else {
			throw ex;
		}
	}
}

由于在initialMulticaster中,线程池为null,故会直接执行invokeListener(listener, event)方法。如图9所示,invokeListener(listener, event)方法实际是调用了listener.onApplicationEvent(event)方法。

当事件为ApplicationStartingEvent时,以上4个监听器的onApplicationEvent(event)方法如图10所示,它们分别进行了以下操作:

① LoggingApplicationListener初始化了loggingSystem

② BackgroundPreinitializer:未执行任何操作

③ DelegatingApplicationListener:未执行任何操作

④ LiquibaseServiceLocatorApplicationListener:未执行任何操作

图10:

/**
 * 当listener为LoggingApplicationListener时
 */
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();
	}
}


private void onApplicationStartingEvent(ApplicationStartingEvent event) {
        // 初始化loggingSystem
	this.loggingSystem = LoggingSystem.get(event.getSpringApplication().getClassLoader());
	this.loggingSystem.beforeInitialize();
}

// ---------------------------------------------------------------

/**
 * 当listener为BackgroundPreinitializer时,由于未识别到ApplicationStartingEvent事件,故不执行任何操作
 */
public void onApplicationEvent(SpringApplicationEvent event) {
	if (!ENABLED) {
		return;
	}
	if (event instanceof ApplicationEnvironmentPreparedEvent
			&& preinitializationStarted.compareAndSet(false, true)) {
		performPreinitialization();
	}
	if ((event instanceof ApplicationReadyEvent || event instanceof ApplicationFailedEvent)
			&& preinitializationStarted.get()) {
		try {
			preinitializationComplete.await();
		}
		catch (InterruptedException ex) {
			Thread.currentThread().interrupt();
		}
	}
}

// ---------------------------------------------------------------

/**
 * 当listener为DelegatingApplicationListener时,由于未识别到ApplicationStartingEvent事件,故不执行任何操作
 */
public void onApplicationEvent(ApplicationEvent event) {
	if (event instanceof ApplicationEnvironmentPreparedEvent) {
		List<ApplicationListener<ApplicationEvent>> delegates = getListeners(
				((ApplicationEnvironmentPreparedEvent) event).getEnvironment());
		if (delegates.isEmpty()) {
			return;
		}
		this.multicaster = new SimpleApplicationEventMulticaster();
		for (ApplicationListener<ApplicationEvent> listener : delegates) {
			this.multicaster.addApplicationListener(listener);
		}
	}
	if (this.multicaster != null) {
		this.multicaster.multicastEvent(event);
	}
}

// ---------------------------------------------------------------

/**
 * 当listener为LiquibaseServiceLocatorApplicationListener时,由于LIQUIBASE_PRESENT为false,故不执行任何操作
 */
public void onApplicationEvent(ApplicationStartingEvent event) {
	if (LIQUIBASE_PRESENT) {
		new LiquibasePresent().replaceServiceLocator();
	}
}

 

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值