共计 4215 个字符,预计需要花费 11 分钟才能阅读完成。
因为目前大部分都是应用 springBoot 开箱即用的开发模式,省略了简单的配置过程。因而记录学习一下 springBoot 启动的过程。springBoot 启动的入口在 SpringApplication.run(Class<?> primarySource, String… args) 这个办法,跟进之后发现创立了一个 SpringApplication 对象并调用了它的 run 办法。
@SpringBootApplication
public class MongotemplateApplication {public static void main(String[] args) {SpringApplication.run(MongotemplateApplication.class, args);
}
}
跟进 SpringApplication 的结构器:
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
this.webApplicationType = WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();}
下面的 WebApplicationType.deduceFromClasspath() 办法解析了以后的环境类型,为前面结构环境做好了筹备。次要是根据以后我的项目中有没有 org.springframework.web.reactive.DispatcherHandler、org.springframework.web.servlet.DispatcherServlet、javax.servlet.Servlet 这几个类来做判断,本文中咱们以 web 环境作为演示,即环境的类型为 SERVLET。下面调用了两次 getSpringFactoriesInstances 这个办法,以设置 SrpingApplication 中的 initializers 和 listeners 属性。进入这个办法中:
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {return getSpringFactoriesInstances(type, new Class<?>[] {});
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
这里重点关注一下 SpringFactoriesLoader.loadFactoryNames(type, classLoader) 这个办法,应用 classLoader 去读取 FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories” 这个文件的内容,并封装成键值对,而后以 type 为 key 获取一个汇合。因而在 SpringApplication 的结构器中获取了 spring.factories 中的 initializers 和 listeners。
接下来就会进入 SpringApplication 的 run 办法,该办法中蕴含了 springBoot 所有的启动流程:
public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
// step1. 获取监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
// 启动监听器
listeners.starting();
try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//step2. 环境筹备
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
//step2. 创立容器
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class}, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {listeners.running(context);
}
catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
上面就比拟重要的步骤做解析:
- 获取并启动监听器
Step1. 获取监听器并启动:
这里同样实用 getSpringFactoriesInstances 办法获取到配置文件中默认的监听器并将之以参数传入,新建了一个 SpringApplicationRunListeners 对象,这个蕴含了一个 EventPublishingRunListener 属性,这个属性封装了之前获取的多个监听器。其 strting 办法公布了一个 ApplicationStartingEvent 事件。这里波及到了 spring 的事件监听模式:
@Override
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);
}
}
}
依据事件类型找到相应的监听器,并调用监听器上的 onApplicationEvent 办法。