@SpringBootApplication(
scanBasePackages = {"com.javaedge.base"}
)
public class BaseApplication {
public BaseApplication() {
}
public static void main(String[] args) {
SpringApplication.run(BaseApplication.class, args);
}
}
静态辅助类,可用于运行使用默认配置(即我们添加的一系列注解)的指定源的 SpringApplication 。
Application.class
Class\> :泛型决定了任何类都可以传入public static ConfigurableApplicationContext run(Class> primarySource, String... args) {
return run(new Class>[] { primarySource }, args);
}
public static ConfigurableApplicationContext run(Class>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
构造一个SpringApplication的实例,然后再调用这里实例的run方法就表示启动SpringBoot。因此,想要分析SpringBoot的启动过程,我们需要熟悉:
创建新 SpringApplication 实例。应用程序上下文将从指定的主要源加载 bean。实例可以在调用 run(String...)之前自定义。
public SpringApplication(Class>... primarySources) {
this(null, primarySources);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 判断是否是web程序:
// jakarta.servlet.Servlet
// org.springframework.web.context.ConfigurableWebApplicationContext
// 须都在类加载器中存在,并设置到webEnvironment属性
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 从 META-INF/spring.factories 中找K=ApplicationContextInitializer的类并实例化后
// 设置到SpringApplication的initializers属性。即找出所有的应用程序初始化器
this.bootstrapRegistryInitializers = new ArrayList<>(
getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 从spring.factories文件中找出key为ApplicationListener的类并实例化后
// 设置到SpringApplication的listeners属性。即找出所有的应用程序事件监听器
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 找出main类,这里是 BaseApplication 类
this.mainApplicationClass = deduceMainApplicationClass();
}
应用程序初始化器,做一些初始化的工作。
用于在刷新之前初始化 Spring ConfigurableApplicationContext 的回调接口。 通常用于需要对应用程序上下文进行某种编程初始化的 Web 应用程序中。如针对上下文的环境注册属性源或激活配置文件。
ApplicationContextInitializer 鼓励处理器检测 Spring 的 Ordered 接口是否已实现或 @Order 注解是否存在,并在调用之前对实例进行相应的排序(如果有)
@FunctionalInterface
public interface ApplicationContextInitializer {
/**
* Initialize the given application context.
* @param applicationContext the application to configure
*/
void initialize(C applicationContext);
}
ApplicationEvent监听器:
@FunctionalInterface
public interface ApplicationListener extends EventListener {
void onApplicationEvent(E event);
static ApplicationListener> forPayload(Consumer consumer) {
return event -> consumer.accept(event.getPayload());
}
}
应用程序的:
应用程序事件监听器跟监听事件是绑定的,如:
先看一些事件和监听器概念:
用于监听SpringApplication的run方法的执行。用于SpringApplicationRunListener监听器的批量执行。
finish:run方法结束之前调用;对应事件的类型是ApplicationReadyEvent或ApplicationFailedEvent
class SpringApplicationRunListeners {
// Log日志类
private final Log log;
// 持有SpringApplicationRunListener集合
private final List listeners;
private final ApplicationStartup applicationStartup;
// run方法执行时立马执行;对应事件类型ApplicationStartingEvent
void starting(ConfigurableBootstrapContext bootstrapContext, Class> mainApplicationClass) {
doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
(step) -> {
if (mainApplicationClass != null) {
step.tag("mainApplicationClass", mainApplicationClass.getName());
}
});
}
// ApplicationContext创建之前并且环境信息准备好的时候调用;对应事件类型ApplicationEnvironmentPreparedEvent
void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) {
doWithListeners("spring.boot.application.environment-prepared",
(listener) -> listener.environmentPrepared(bootstrapContext, environment));
}
// ApplicationContext创建好并且在source加载之前调用一次;没有具体的对应事件
void contextPrepared(ConfigurableApplicationContext context) {
doWithListeners("spring.boot.application.context-prepared", (listener) -> listener.contextPrepared(context));
}
// ApplicationContext创建并加载之后,并在refresh之前调用
// 对应事件类型ApplicationPreparedEvent
void contextLoaded(ConfigurableApplicationContext context) {
doWithListeners("spring.boot.application.context-loaded", (listener) -> listener.contextLoaded(context));
}
void started(ConfigurableApplicationContext context, Duration timeTaken) {
doWithListeners("spring.boot.application.started", (listener) -> listener.started(context, timeTaken));
}
void ready(ConfigurableApplicationContext context, Duration timeTaken) {
doWithListeners("spring.boot.application.ready", (listener) -> listener.ready(context, timeTaken));
}
void failed(ConfigurableApplicationContext context, Throwable exception) {
doWithListeners("spring.boot.application.failed",
(listener) -> callFailedListener(listener, context, exception), (step) -> {
step.tag("exception", exception.getClass().toString());
step.tag("message", exception.getMessage());
});
}
private void callFailedListener(SpringApplicationRunListener listener, ConfigurableApplicationContext context,
Throwable exception) {
try {
listener.failed(context, exception);
}
catch (Throwable ex) {
if (exception == null) {
ReflectionUtils.rethrowRuntimeException(ex);
}
if (this.log.isDebugEnabled()) {
this.log.error("Error handling failed", ex);
}
else {
String message = ex.getMessage();
message = (message != null) ? message : "no error message";
this.log.warn("Error handling failed (" + message + ")");
}
}
}
private void doWithListeners(String stepName, Consumer listenerAction) {
doWithListeners(stepName, listenerAction, null);
}
private void doWithListeners(String stepName, Consumer listenerAction,
Consumer stepAction) {
StartupStep step = this.applicationStartup.start(stepName);
this.listeners.forEach(listenerAction);
if (stepAction != null) {
stepAction.accept(step);
}
step.end();
}
}
SpringApplicationRunListener目前只有一个实现类EventPublishingRunListener:
/**
* SpringApplicationRunListener to publish SpringApplicationEvents.
* Uses an internal ApplicationEventMulticaster for the events that are fired
* before the context is actually refreshed.
*/
class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
private final SpringApplication application;
private final String[] args;
private final SimpleApplicationEventMulticaster initialMulticaster;
@Override
public void starting(ConfigurableBootstrapContext bootstrapContext) {
multicastInitialEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
}
@Override
public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext,
ConfigurableEnvironment environment) {
multicastInitialEvent(
new ApplicationEnvironmentPreparedEvent(bootstrapContext, this.application, this.args, environment));
}
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
multicastInitialEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
for (ApplicationListener> listener : this.application.getListeners()) {
if (listener instanceof ApplicationContextAware contextAware) {
contextAware.setApplicationContext(context);
}
context.addApplicationListener(listener);
}
multicastInitialEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
@Override
public void started(ConfigurableApplicationContext context, Duration timeTaken) {
context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context, timeTaken));
AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);
}
@Override
public void ready(ConfigurableApplicationContext context, Duration timeTaken) {
context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context, timeTaken));
AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);
}
@Override
public void failed(ConfigurableApplicationContext context, Throwable exception) {
ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception);
if (context != null && context.isActive()) {
// Listeners have been registered to the application context so we should
// use it at this point if we can
context.publishEvent(event);
}
else {
// An inactive context may not have a multicaster so we use our multicaster to
// call all the context's listeners instead
if (context instanceof AbstractApplicationContext abstractApplicationContext) {
for (ApplicationListener> listener : abstractApplicationContext.getApplicationListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
this.initialMulticaster.setErrorHandler(new LoggingErrorHandler());
this.initialMulticaster.multicastEvent(event);
}
}
// 广播事件出去
private void multicastInitialEvent(ApplicationEvent event) {
refreshApplicationListeners();
this.initialMulticaster.multicastEvent(event);
}
private void refreshApplicationListeners() {
this.application.getListeners().forEach(this.initialMulticaster::addApplicationListener);
}
private static class LoggingErrorHandler implements ErrorHandler {
private static final Log logger = LogFactory.getLog(EventPublishingRunListener.class);
@Override
public void handleError(Throwable throwable) {
logger.warn("Error calling ApplicationEventListener", throwable);
}
}
}
它把监听过程封装成SpringApplicationEvent事件,并让内部属性initialMulticaster,ApplicationEventMulticaster接口的实现类SimpleApplicationEventMulticaster广播出去:
广播出去的事件对象会被SpringApplication中的listeners属性进行处理。
所以SpringApplicationRunListener和ApplicationListener之间的关系是通过ApplicationEventMulticaster广播出去的SpringApplicationEvent所联系。
调用getSpringFactoriesInstances
获取配置的监听器名称,并实例化所有的类。
SpringApplicationRunListener
所有监听器配置在 pring.factories :
public ConfigurableApplicationContext run(String... args) {
// 开始执行,记录开始时间
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
// 设置系统属性 java.awt.headless 的值,默认为true
configureHeadlessProperty();
// 获取SpringApplicationRunListeners,内部只有一个EventPublishingRunListener
// 创建所有 Spring 运行监听器并发布应用启动事件
SpringApplicationRunListeners listeners = getRunListeners(args);
// 会封装成SpringApplicationEvent事件然后广播出去给SpringApplication中的listeners所监听
// 这里接受ApplicationStartedEvent事件的listener会执行相应操作
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
// 初始化默认应用参数类
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 根据运行监听器和应用参数来准备 Spring 环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
Banner printedBanner = printBanner(environment);
// 创建Spring容器,即创建应用上下文
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
// 准备应用上下文
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
// 容器创建完成之后执行额外一些操作
afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
}
// 广播出ApplicationReadyEvent事件给相应的监听器执行
// 发布应用上下文启动完成事件
listeners.started(context, timeTakenToStartup);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
handleRunFailure(context, ex, listeners);
throw new IllegalStateException(ex);
}
try {
if (context.isRunning()) {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
// 发布应用上下文就绪事件
listeners.ready(context, timeTakenToReady);
}
}
catch (Throwable ex) {
if (ex instanceof AbandonedRunException) {
throw ex;
}
// 过程报错的话会执行一些异常操作
// 然后广播出ApplicationFailedEvent事件给相应的监听器执行
handleRunFailure(context, ex, null);
throw new IllegalStateException(ex);
}
// 返回Spring容器
return context;
}
private void configureHeadlessProperty() {
System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS,
System.getProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
}