1.从应用程序启动入口开始追踪代码:
SpringApplication.run(SpringbootDemoApplication.class, args);
2.进入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();
- this.bootstrapRegistryInitializers = new ArrayList<>(
- getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
- setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
- setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
- this.mainApplicationClass = deduceMainApplicationClass();
- }
这个步骤做了以下几件事:
a.初始化资源加载器,但是从上下文可以看出是null
b.设置主资源类,即第一步传过来的SpringbootDemoApplication类
c.推断webApplicationType的类型:WebApplicationType.SERVLET
d.设置bootstrapRegistryInitializers数据,通过SpringFactoriesLoader从META-INF/spring.factories目录加载key为BootstrapRegistryInitializer的数据并初始化
e.设置initializers,通过SpringFactoriesLoader从上下文中所以jar根目录META-INF/spring.factories目录加载key为ApplicationContextInitializer的数据并初始化
f.设置listeners,通过SpringFactoriesLoader从上下文中所以jar根目录META-INF/spring.factories目录加载key为ApplicationListener的数据并初始化
j.推断主应用类,即SpringbootDemoApplication类
3.接着继续进入SpringApplication类的run方法中,如下代码:
- public ConfigurableApplicationContext run(String... args) {
- long startTime = System.nanoTime();
- // a.创建一个springboot上下文对象
- DefaultBootstrapContext bootstrapContext = createBootstrapContext();
- ConfigurableApplicationContext context = null;
- configureHeadlessProperty();
- // b.获取并启动监听的listeners
- SpringApplicationRunListeners listeners = getRunListeners(args);
- listeners.starting(bootstrapContext, this.mainApplicationClass);
- try {
- // c.初始化应用环境
- ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
- ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
- configureIgnoreBeanInfo(environment);
- // 打印启动banner数据
- Banner printedBanner = printBanner(environment);
- // d.初始化应用上下文
- context = createApplicationContext();
- context.setApplicationStartup(this.applicationStartup);
- // e.刷新应用上下文前的准备工作
- prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
- // f.刷新应用上下文
- refreshContext(context);
- // j.刷新应用上下文之后的扩展功能
- afterRefresh(context, applicationArguments);
- Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
- if (this.logStartupInfo) {
- new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
- }
- listeners.started(context, timeTakenToStartup);
- // h.调用ApplicationRunner和CommandLineRunner的run方法
- callRunners(context, applicationArguments);
- }
- catch (Throwable ex) {
- handleRunFailure(context, ex, listeners);
- throw new IllegalStateException(ex);
- }
- try {
- Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
- listeners.ready(context, timeTakenToReady);
- }
- catch (Throwable ex) {
- handleRunFailure(context, ex, null);
- throw new IllegalStateException(ex);
- }
- return context;
- }
接下来具体解释一下,每一步的细节:
a.创建springboot上下文对象:创建一个类型为DefaultBootstrapContext的上下文对象,并且将第二步获取过来的bootstrapRegistryInitializers执行初始化操作,执行initialize方法
- private DefaultBootstrapContext createBootstrapContext() {
- DefaultBootstrapContext bootstrapContext = new DefaultBootstrapContext();
- this.bootstrapRegistryInitializers.forEach((initializer) -> initializer.initialize(bootstrapContext));
- return bootstrapContext;
- }
BootstrapRegistryInitializer接口类:
- @FunctionalInterface
- public interface BootstrapRegistryInitializer {
-
- /**
- * Initialize the given {@link BootstrapRegistry} with any required registrations.
- * @param registry the registry to initialize
- */
- void initialize(BootstrapRegistry registry);
-
- }
可以自行实现该接口并做某些初始化作用,这个初始化的时机比较早。
b.获取并启动监听的listeners:获取并实例化所有类型为SpringApplicationRunListener的listener
- 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);
- }
启动listener
- void starting(ConfigurableBootstrapContext bootstrapContext, Class> mainApplicationClass) {
- doWithListeners("spring.boot.application.starting", (listener) -> listener.starting(bootstrapContext),
- (step) -> {
- if (mainApplicationClass != null) {
- step.tag("mainApplicationClass", mainApplicationClass.getName());
- }
- });
- }
进入org.springframework.boot.context.event.EventPublishingRunListener#starting方法中(说明:EventPublishingRunListener这个runlistener是通过反射初始化的,通过getRunListeners反射调用的是EventPublishingRunListener(SpringApplication application, String[] args) 这个构造方法,有兴趣可以看看,里面初始化了多播器:initialMulticaster和当前应用对象:application):发布了一个ApplicationStartingEvent事件对象
- @Override
- public void starting(ConfigurableBootstrapContext bootstrapContext) {
- this.initialMulticaster
- .multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
- }
继续追踪到org.springframework.context.event.SimpleApplicationEventMulticaster#multicastEvent(org.springframework.context.ApplicationEvent, org.springframework.core.ResolvableType)方法:
- 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);
- }
- }
- }
继续追到org.springframework.context.event.SimpleApplicationEventMulticaster#doInvokeListener:
- private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
- try {
- listener.onApplicationEvent(event);
- }
- catch (ClassCastException ex) {
- // 省略部分代码...
- }
- }
最终执行各个listener的onApplicationEvent方法。
springboot中所有的事件发布都是由org.springframework.boot.context.event.EventPublishingRunListener这个类来发布完成的,它会在容器初始化的各个阶段发布各种不同的事件,关注了这个事件的监听器就能接受到,然后执行对应的方法。
c.初始化应用环境,代码如下:
- private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
- ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
- ApplicationArguments applicationArguments, Banner printedBanner) {
- context.setEnvironment(environment);
- postProcessApplicationContext(context);
- // 执行第二步获取的initializers方法
- applyInitializers(context);
- // 发布一个ApplicationContextInitializedEvent类型的事件,告诉listener准备监听
- listeners.contextPrepared(context);
- bootstrapContext.close(context);
- if (this.logStartupInfo) {
- logStartupInfo(context.getParent() == null);
- logStartupProfileInfo(context);
- }
- // Add boot specific singleton beans
- ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
- beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
- if (printedBanner != null) {
- beanFactory.registerSingleton("springBootBanner", printedBanner);
- }
- if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
- ((AbstractAutowireCapableBeanFactory) beanFactory).setAllowCircularReferences(this.allowCircularReferences);
- if (beanFactory instanceof DefaultListableBeanFactory) {
- ((DefaultListableBeanFactory) beanFactory)
- .setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
- }
- }
- if (this.lazyInitialization) {
- context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
- }
- context.addBeanFactoryPostProcessor(new PropertySourceOrderingBeanFactoryPostProcessor(context));
- // Load the sources
- Set
- Assert.notEmpty(sources, "Sources must not be empty");
- load(context, sources.toArray(new Object[0]));
- listeners.contextLoaded(context);
- }
d.初始化应用上下文:
- context = createApplicationContext();
- context.setApplicationStartup(this.applicationStartup);
e.刷新应用上下文前的准备工作(跟spring无缝对接起来)org.springframework.context.support.AbstractApplicationContext#refresh:
- public void refresh() throws BeansException, IllegalStateException {
- synchronized (this.startupShutdownMonitor) {
- StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
-
- // Prepare this context for refreshing.
- prepareRefresh();
-
- // Tell the subclass to refresh the internal bean factory.
- ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
-
- // Prepare the bean factory for use in this context.
- prepareBeanFactory(beanFactory);
-
- try {
- // Allows post-processing of the bean factory in context subclasses.
- postProcessBeanFactory(beanFactory);
-
- StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
- // Invoke factory processors registered as beans in the context.
- invokeBeanFactoryPostProcessors(beanFactory);
-
- // Register bean processors that intercept bean creation.
- registerBeanPostProcessors(beanFactory);
- beanPostProcess.end();
-
- // Initialize message source for this context.
- initMessageSource();
-
- // Initialize event multicaster for this context.
- initApplicationEventMulticaster();
-
- // Initialize other special beans in specific context subclasses.
- onRefresh();
-
- // Check for listener beans and register them.
- registerListeners();
-
- // Instantiate all remaining (non-lazy-init) singletons.
- finishBeanFactoryInitialization(beanFactory);
-
- // Last step: publish corresponding event.
- finishRefresh();
- }
-
- catch (BeansException ex) {
- // 省略代码...
- }
-
- finally {
- // Reset common introspection caches in Spring's core, since we
- // might not ever need metadata for singleton beans anymore...
- resetCommonCaches();
- contextRefresh.end();
- }
- }
- }
h.调用ApplicationRunner和CommandLineRunner的run方法,它的执行时机是容器启动完成的时候,实现对应的接口即可:
- private void callRunners(ApplicationContext context, ApplicationArguments args) {
- List
- runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
- runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
- AnnotationAwareOrderComparator.sort(runners);
- for (Object runner : new LinkedHashSet<>(runners)) {
- if (runner instanceof ApplicationRunner) {
- callRunner((ApplicationRunner) runner, args);
- }
- if (runner instanceof CommandLineRunner) {
- callRunner((CommandLineRunner) runner, args);
- }
- }
- }