SpringBoot 是一个基于 Spring 框架的疾速开发框架,旨在简化 Spring 应用程序的开发和部署。在本文中,咱们将深入分析 SpringBoot 启动过程的源代码,并提供必要的解释和阐明。
SpringBoot启动过程简介
SpringBoot应用程序的启动过程能够分为以下几个步骤:

加载应用程序上下文
扫描应用程序中的所有组件
主动配置应用程序环境
启动嵌入式Web服务器

在上面的章节中,咱们将逐个剖析这些步骤的源代码。
加载应用程序上下文
SpringBoot 应用程序的上下文是一个蕴含所有应用程序组件的容器。在启动过程中,SpringBoot 会加载并初始化这个容器。
这个步骤的源代码在SpringApplication类中。具体来说,SpringApplication类的run办法是这个过程的入口点。在这个办法中,Spring Boot会通过调用createApplicationContext办法来创立应用程序上下文。
上面是createApplicationContext办法的源代码:
protected ConfigurableApplicationContext createApplicationContext() {

Class<?> contextClass = this.applicationContextClass;if (contextClass == null) {    try {        switch (this.webApplicationType) {            case SERVLET:                contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);                break;            case REACTIVE:                contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);                break;            default:                contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);        }    }    catch (ClassNotFoundException ex) {        throw new IllegalStateException(                "Unable to create a default ApplicationContext, " +                "please specify an ApplicationContextClass", ex);    }}return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);

}
复制代码
在这个办法中,SpringBoot 会依据应用程序类型(Servlet或Reactive)抉择适合的上下文类。而后,它会应用 Java 反射机制来实例化这个类并返回一个可配置的应用程序上下文对象。
扫描应用程序中的所有组件
在上一步中,SpringBoot创立了应用程序上下文。在这一步中,SpringBoot会扫描应用程序中的所有组件并将它们注册到应用程序上下文中。
这个步骤的源代码在SpringApplication类中的scan办法中。具体来说,在这个办法中,SpringBoot 会创立一个SpringBootBeanDefinitionScanner对象,并应用它来扫描应用程序中的所有组件。
上面是scan办法的源代码:
private void scan(String... basePackages) {

if (ObjectUtils.isEmpty(basePackages)) {    return;}ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(        this.includeFilters, this.excludeFilters, this.resourceLoader);scanner.setResourceLoader(this.resourceLoader);scanner.setEnvironment(this.environment);scanner.setIncludeAnnotationConfig(this.useAnnotatedConfig);scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {    @Override    protected boolean matchClassName(String className) {        return getExcludeClassNames().contains(className);    }});for (String basePackage : basePackages) {    scanner.findCandidateComponents(basePackage).forEach(this.componentDefinitions::add);}

}
复制代码
在这个办法中,SpringBoot 会创立一个ClassPathScanningCandidateComponentProvider对象,并应用它来扫描应用程序中的所有组件。这个对象会扫描指定包门路下的所有类,并将它们转换为 Spring 的 Bean 定义。这些 Bean 定义将被注册到应用程序上下文中。
主动配置应用程序环境
在上一步中,SpringBoot将应用程序中的所有组件注册到应用程序上下文中。在这一步中,SpringBoot将主动配置应用程序环境,包含配置数据源、事务管理器、JPA等。
这个步骤的源代码在SpringApplication类中的configureEnvironment办法中。在这个办法中,Spring Boot会创立一个SpringApplicationRunListeners对象,并应用它来配置应用程序环境。
上面是configureEnvironment办法的源代码:
private void configureEnvironment(ConfigurableEnvironment environment, String[] args) {

if (this.addCommandLineProperties) {    ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);    environment.getPropertySources().addLast(new CommandLinePropertySource(applicationArguments));}this.listeners.environmentPrepared(environment);if (this.logStartupInfo) {    this.logStartupInfo(environment);}ConfigurationPropertySources.attach(environment);Binder.get(environment).bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(this.sources));if (!this.isCustomEnvironment) {    EnvironmentConverter.configureEnvironment(environment, this.deduceEnvironmentClass());}this.listeners.environmentPrepared(environment);

}
复制代码
在这个办法中,SpringBoot 会创立一个ApplicationArguments对象,并将其转换为一个命令行属性源。而后,它会调用listeners中的environmentPrepared办法来告诉应用程序环境曾经筹备好了。随后,SpringBoot 会绑定属性源到应用程序环境中,并调用listeners中的environmentPrepared办法来告诉应用程序环境曾经筹备好了。
启动嵌入式Web服务器
在上一步中,SpringBoot 将应用程序环境主动配置实现。在这一步中,SpringBoot 将启动嵌入式Web服务器,以便应用程序可能提供 Web 服务。
这个步骤的源代码在SpringApplication类中的run办法中。具体来说,在这个办法中,SpringBoot 会依据应用程序类型(Servlet或Reactive)抉择适合的嵌入式Web服务器,并应用它来启动应用程序。
上面是run办法的源代码:
public ConfigurableApplicationContext run(String... args) {

StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();configureHeadlessProperty();SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting();try {    ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);    ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);    configureIgnoreBeanInfo(environment);    Banner printedBanner = printBanner(environment);    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;

}
复制代码
在这个办法中,SpringBoot 会应用一个StopWatch对象来计算应用程序启动工夫。而后,它会调用listeners中的starting办法来告诉应用程序行将启动。接着,SpringBoot 会筹备应用程序环境,并应用它来创立应用程序上下文。随后,SpringBoot 会调用listeners中的started办法来告诉应用程序曾经启动。最初,SpringBoot 会调用callRunners办法来运行所有的CommandLineRunner和ApplicationRunner组件。
总结
在本文中,咱们深入分析了 SpringBoot 应用程序的启动过程的源代码。咱们理解了 SpringBoot 如何加载应用程序上下文、扫描应用程序中的所有组件、主动配置应用程序环境以及启动嵌入式Web服务器。这些步骤的源代码展现了 SpringBoot 如何简化应用程序的开发和部署。