因为目前大部分都是应用 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;    }

上面就比拟重要的步骤做解析:

  1. 获取并启动监听器
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 办法。