Spring Boot 启动时做了什么

Posted 恍若昨夕

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot 启动时做了什么相关的知识,希望对你有一定的参考价值。

注解

@SpringBootApplication注解 中包括三个注解:

  • @EnableAutoConfiguration:借助@Import的帮助,将所有符合自动配置条件的bean定义加载到IoC容器
  • @Configuration:Spring Ioc容器的配置类,
  • @ComponentScan:组件扫描,可自动发现和装配Bean,功能其实就是自动扫描并加载符合条件的组件或者bean定义,最终将这些bean定义加载到IoC容器中.默认扫描SpringApplication的run方法里的class所在的包路径下文件,所以最好将该启动类放到根包路径下

启动方法

创建SpringApplication实例

    public SpringApplication(Class... primarySources) {
        this((ResourceLoader)null, primarySources);
    }

    public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
        this.sources = new LinkedHashSet();
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = new HashSet();
        this.isCustomEnvironment = false;
        this.lazyInitialization = false;
        // 初始化资源加载器
        this.resourceLoader = resourceLoader;
        // 断言主要资源类不为空
        Assert.notNull(primarySources, "PrimarySources must not be null");
        // 初始化主要加载资源类集合
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
        // 判断项目类型
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
        // 设置初始化器
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
        //设置监听器
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
        //推断程序主类
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }

初始化主要加载资源类集合

判断项目类型

	public enum WebApplicationType {
		NONE,
	    SERVLET,
	    REACTIVE;
	
	    private static final String[] SERVLET_INDICATOR_CLASSES = new String[]{"javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext"};
	    private static final String WEBMVC_INDICATOR_CLASS = "org.springframework.web.servlet.DispatcherServlet";
	    private static final String WEBFLUX_INDICATOR_CLASS = "org.springframework.web.reactive.DispatcherHandler";
	    private static final String JERSEY_INDICATOR_CLASS = "org.glassfish.jersey.servlet.ServletContainer";
	    private static final String SERVLET_APPLICATION_CONTEXT_CLASS = "org.springframework.web.context.WebApplicationContext";
	    private static final String REACTIVE_APPLICATION_CONTEXT_CLASS = "org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext";
	
	    private WebApplicationType() {
	    }
	
	    static WebApplicationType deduceFromClasspath() {
	        if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)) {
	            return REACTIVE;
	        } else {
	            String[] var0 = SERVLET_INDICATOR_CLASSES;
	            int var1 = var0.length;
	
	            for(int var2 = 0; var2 < var1; ++var2) {
	                String className = var0[var2];
	                if (!ClassUtils.isPresent(className, (ClassLoader)null)) {
	                    return NONE;
	                }
	            }
	
	            return SERVLET;
	        }
	    }
	}

根据classpath中是否包含指定类
1.REACTIVE:ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null) && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", (ClassLoader)null)
2.SERVLET:(!ClassUtils.isPresent("javax.servlet.Servlet", (ClassLoader)null)) && (!ClassUtils.isPresent("org.springframework.web.context.ConfigurableWebApplicationContext", (ClassLoader)null))
3.NONE

设置应用上线文初始化器 ApplicationContextInitializer

路径下META-INF/spring.factories文件ApplicationContextInitializer 接口的所有配置的类路径名称,用来初始化指定的 Spring 应用上下文,如注册属性资源、激活 Profiles 等。

  1. 获取类加载器
  2. 获取ApplicationContextInitializer实例名称
  3. 创建初始化器实例
  4. 给初始化器实例排序

设置监听器 ApplicationListener

路径下META-INF/spring.factories文件,使用初始化器相同的方法设置

设置程序的主类

执行run方法




以上是关于Spring Boot 启动时做了什么的主要内容,如果未能解决你的问题,请参考以下文章

1. SOFAJRaft源码分析— SOFAJRaft启动时做了什么?

一张图,理顺 Spring Boot应用在启动阶段执行代码的几种方式

解决spring-boot启动中碰到的问题:Cannot determine embedded database driver class for database type NONE(转)(代码片段

一张图帮你记忆,Spring Boot 应用在启动阶段执行代码的几种方式

spring boot到底帮我们做了那些事?

一张图,理顺 Spring Boot应用在启动阶段执行代码的几种方式