因为目前大部分都是应用 springBoot 开箱即用的开发模式,省略了简单的配置过程。因而记录学习一下 springBoot 启动的过程。springBoot 启动的入口在 SpringApplication.run(Class<?> primarySource, String... args) 这个办法,跟进之后发现创立了一个 SpringApplication 对象并调用了它的 run 办法。
@SpringBootApplicationpublic 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 办法。