Spring源码1:初始化SpringApplication实例

目录

1. 项目结构

2. 启动SpringApplication

3. SpringApplication构造函数

    3.1 通过加载各个Web类型的容器类,判断当前模块web类型

    3.2 加载Application初始化器

    3.3 加载Application监听器

    3.4 找到启动类

4. 返回结果

5. 总结


1. 项目结构

本文基于spring的2.1.3版本, 进行了模块的搭建, 包引用关系如下:

<parent>
    <!-- 导入2.1.3的springboot -->
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.3.RELEASE</version>
    <relativePath/>
</parent>

<properties>
    <!-- jdk版本为1.8 -->
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <!-- 导入spring web相关包 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- 导入通用mapper包,通用mapper会自动导入mybatis包 -->
    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper-spring-boot-starter</artifactId>
        <version>2.1.5</version>
    </dependency>
    <!-- mysql JDBC驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!-- mysql 连接池 -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-dbcp2</artifactId>
        <version>2.6.0</version>
    </dependency>
</dependencies>

2. 启动项目

springboot启动类写法如下, 加上@SpringBootApplication注解, 表明这是一个springboot的启动类, springboot会通过@SpringBootApplication自动扫描配置类,
自动导入和配置各个spring-boot-starter组件

@SpringBootApplication
//开启数据库事务
@EnableTransactionManagement
public class YanggxApplication {
    public static void main(String[] args) {
        //启动spring项目
        SpringApplication.run(YanggxApplication.class, args);
    }
}

通过调用SpringApplication.run(YanggxApplication.class, args), 启动了spring项目, 该方法执行了两个操作, 首先初始化了一个SpringApplication实例, 然后调用run方法

public class SpringApplication {
    //SpringApplication类静态run方法
    public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
        //首先初始化一个SpringApplication实例
        //然后调用该实例的run方法
        return new SpringApplication(primarySources).run(args);
    }
}

3. SpringApplication构造函数

SpringApplication构造函数执行了四件事情

  1. 通过加载各个Web类型的容器类,判断当前模块web类型
  2. 加载Application初始化器
  3. 加载Application监听器
  4. 找到启动类
//SpringApplication类
//只列出几个重要的字段和方法
public class SpringApplication {
    
    //SpringApplication默认web容器类
    public static final String DEFAULT_SERVLET_WEB_CONTEXT_CLASS = "org.springframework.boot."
            + "web.servlet.context.AnnotationConfigServletWebServerApplicationContext";

    //banner名称,默认为banner.txt
    public static final String BANNER_LOCATION_PROPERTY_VALUE = SpringApplicationBannerPrinter.DEFAULT_BANNER_LOCATION;

    //banner位置key,默认为spring.banner.location
    public static final String BANNER_LOCATION_PROPERTY = SpringApplicationBannerPrinter.BANNER_LOCATION_PROPERTY;

    
    //调用main函数的类,也就是YanggxApplication.class
    private Class<?> mainApplicationClass;
    
    //bean名称生成器
    private BeanNameGenerator beanNameGenerator;

    //spring的环境,我们使用的是ServletWeb环境
    private ConfigurableEnvironment environment;

    //web类型
    private WebApplicationType webApplicationType;

    //Application初始化器
    //springboot启动过程中执行其initialize方法
    private List<ApplicationContextInitializer<?>> initializers;

    //Application监听器
    //springboot启动过程执行其onApplicationEvent方法
    private List<ApplicationListener<?>> listeners;
    
    /**
     * SpringApplication构造函数
     * @param resourceLoader 资源加载器的策略接口,传参null,
     * @param primarySources 传参YanggxApplication.class
     */
    public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
        this.resourceLoader = resourceLoader;
        Assert.notNull(primarySources, "PrimarySources must not be null");
        //Set去重
        this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
        // 3.1 通过加载各个Web类型的容器类,判断当前模块web类型
        //
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
    
        // 3.2 加载Application初始化器
        // 获取所有"META-INF/spring.factories"文件中维护的ApplicationContextInitializer子类列表
        // org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer
        // org.springframework.boot.context.ContextIdApplicationContextInitializer  
        // org.springframework.boot.context.config.DelegatingApplicationContextInitializer  
        // org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer   
        // org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
        setInitializers((Collection) getSpringFactoriesInstances(
                ApplicationContextInitializer.class));
    
        // 3.3 加载Application监听器
        // 获取所有"META-INF/spring.factories"文件中维护的ApplicationListener子类列表
        // org.springframework.boot.ClearCachesApplicationListener
        // org.springframework.boot.builder.ParentContextCloserApplicationListener
        // org.springframework.boot.context.FileEncodingApplicationListener
        // org.springframework.boot.context.config.AnsiOutputApplicationListener
        // org.springframework.boot.context.config.ConfigFileApplicationListener
        // org.springframework.boot.context.config.DelegatingApplicationListener
        // org.springframework.boot.context.logging.ClasspathLoggingApplicationListener
        // org.springframework.boot.context.logging.LoggingApplicationListener
        // org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
        // org.springframework.boot.autoconfigure.BackgroundPreinitializer
        // 加载的这些类都是ApplicationListener的子类
        setListeners((Collection) getSpringFactoriesInstances(
                 ApplicationListener.class));
    
        // 3.4 找到启动类
        // 抛出一个RuntimeException,然后通过堆栈信息找到启动类 
        this.mainApplicationClass = deduceMainApplicationClass();
    }
}

 

3.1 通过加载各个Web类型的容器类,判断当前模块web类型

调用WebApplicationType枚举的deduceFromClasspath方法,判断当前模块的web类型,web类型分为三类,其判断逻辑如下

  1. REACTIVE WEB类型(REACTIVE)
    • 能加载org.springframework.web.reactive.DispatcherHandler
    • 不能加载org.springframework.web.servlet.DispatcherServlet, 并且不能加载org.glassfish.jersey.servlet.ServletContainer
  2. 非WEB类型(NONE)
    • 不能加载javax.servlet.Servlet
    • 不能加载org.springframework.web.context.ConfigurableWebApplicationContext
  3. SERVLET WEB类型(SERVLET)
    • 如果不是REACTIVE类型和非WEB类型, 那么默认为SERVLET类型
//Web应用类型
public enum WebApplicationType {
    //不是WEB类型
    NONE,

    //SERVLE Web类型
    SERVLET,

    //REACTIVE Web类型
    REACTIVE;

    private static final String[] SERVLET_INDICATOR_CLASSES = { "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";

    static WebApplicationType deduceFromClasspath() {
        //能加载org.springframework.web.reactive.DispatcherHandler
        //不能加载org.springframework.web.servlet.DispatcherServlet
        //不能加载org.glassfish.jersey.servlet.ServletContainer
        //返回REACTIVE
        if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
                && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
                && !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
            return WebApplicationType.REACTIVE;
        }
        //不能加载javax.servlet.Servlet
        //不能加载org.springframework.web.context.ConfigurableWebApplicationContext
        //返回None
        for (String className : SERVLET_INDICATOR_CLASSES) {
            if (!ClassUtils.isPresent(className, null)) {
                return WebApplicationType.NONE;
            }
        }
        //默认返回SERVLET
        return WebApplicationType.SERVLET;
    }
}

 

3.2 加载Application初始化器

getSpringFactoriesInstances方法非常重要, 之后很多地方都调用了这个方法,
主要作用是从META-INF/spring.factories文件中获取指定类型这里的子类列表, 去重, 排序, 执行步骤如下:

  1. 调用SpringFactoriesLoader的loadFactoryNames方法, 扫描各个jar包中的META-INF/spring.factories文件, 缓存文件中的类名配置, 并返回指定的子类名称列表
  2. 实例化所有子类对象
  3. 子类对象按照@Order注解进行排序

当前传入的是ApplicationContextInitializer.class,也就是返回是ApplicationContextInitializer的子类对象列表

public class SpringApplication {
    //获取所有META-INF/spring.factories文件中维护的类型为type的对象列表
    //实例化对象列表, 构造函数传参为parameterTypes和args
    private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
            Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = getClassLoader();
        //调用SpringFactoriesLoader的loadFactoryNames方法, 
        //扫描各个jar包中的META-INF/spring.factories文件, 
        //缓存文件中的类名配置, 
        //并返回ApplicationContextInitializer的子类名称列表
        //Set保证数据不重复
        Set<String> names = new LinkedHashSet<>(
                SpringFactoriesLoader.loadFactoryNames(type, classLoader));
        //根据类型获取对应的实例
        List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
                classLoader, args, names);
        //按照@Order注解排序,
        //没有注解的不参与排序
        AnnotationAwareOrderComparator.sort(instances);
        return instances;
    }
    
    //实例化所有类型为type的子类对象
    //names是类名列表
    //parameterTypes和args是构造函数的参数
    private <T> List<T> createSpringFactoriesInstances(Class<T> type,
            Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,
            Set<String> names) {
        List<T> instances = new ArrayList<>(names.size());
        for (String name : names) {
            try {
                //利用反射实例化对象
                Class<?> instanceClass = ClassUtils.forName(name, classLoader);
                //断言,确保能加载类
                Assert.isAssignable(type, instanceClass);
                //通过构造函数实例化对象
                Constructor<?> constructor = instanceClass
                        .getDeclaredConstructor(parameterTypes);
                T instance = (T)
                BeanUtils.instantiateClass(constructor, args);
                instances.add(instance);
            }
            catch (Throwable ex) {
                throw new IllegalArgumentException(
                        "Cannot instantiate " + type + " : " + name, ex);
            }
        }
        //返回对象列表
        return instances;
    }
}

 SpringFactoriesLoader.loadFactoryNames()

这个方法比较重要, 后面的很多代码都会用到该方法,首次加载所有META-INF/spring.factories中配置的类名, 缓存到ConcurrentReferenceHashMap中, 之后每次调用该方法, 都会先从ConcurrentReferenceHashMap缓存中获取对象

public final class SpringFactoriesLoader {

    //所有jar包中的META-INF/spring.factories文件
    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

    //缓存
    private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap<>();
    
    //获取类型为factoryClass对象的所有子类名称
    public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();
        //获取名称列表,如果为空,那么返回Collections.emptyList()
        return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
    }

    //获取所有META-INF/spring.factories文件中维护的子类名
    private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
        //缓存中获取
        //如果缓存中存在,那么立即返回
        MultiValueMap<String, String> result = cache.get(classLoader);
        if (result != null) {
            return result;
        }

        try {  
            //缓存中不存在的话,遍历各个jar包中的spring.factories文件
            Enumeration<URL> urls = (classLoader != null ?
                    classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                    ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
            result = new LinkedMultiValueMap<>();
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                UrlResource resource = new UrlResource(url);
                Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                for (Map.Entry<?, ?> entry : properties.entrySet()) {
                    //封装固定格式的Map
                    String factoryClassName = ((String) entry.getKey()).trim();
                    for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
                        result.add(factoryClassName, factoryName.trim());
                    }
                }
            }
            //放入缓存中, 之后可以从缓存中获取
            cache.put(classLoader, result);
            //返回对象
            return result;
        }
        catch (IOException ex) {
            throw new IllegalArgumentException("Unable to load factories from location [" +
                    FACTORIES_RESOURCE_LOCATION + "]", ex);
        }
    }
}

3.3 加载Application监听器

方法同上, 从所有META-INF/spring.factories中获取ApplicationListener的子类列表, 去重, 排序, 并维护到listeners列表中, 执行步骤如下

  1. 调用SpringFactoriesLoader的loadFactoryNames方法, 直接从ConcurrentReferenceHashMap缓存中获取到ApplicationListener的子类名称列表
  2. 实例化ApplicationListener子类对象
  3. ApplicationListener对象按照@Order注解进行排序

3.4 找到启动类

通过抛出一个RuntimeException, 遍历其堆栈信息, 获取到类名中包含main方法的类, 实例化这个类

private Class<?> deduceMainApplicationClass() {
    try {
        //通过一个RuntimeException,获取器堆栈信息
        StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
        for (StackTraceElement stackTraceElement : stackTrace) {
            if ("main".equals(stackTraceElement.getMethodName())) {
                //堆栈中包含main方法,实例化一个该类的对象
                return Class.forName(stackTraceElement.getClassName());
            }
        }
    }
    catch (ClassNotFoundException ex) { }
    return null;
}

4. 执行结果

初始化的SpringApplication实例

{
    "primarySources":[ //Set
        com.yanggx.spring.YanggxApplication.class
    ],
    "source":[],//LinkedHashSet
    "mainApplicationClass": com.yanggx.spring.YanggxApplication.class,
    "bannerMode":"CONSOLE",
    "logStartupInfo":true,
    "addCommandLineProperties":true,
    "addConversionService":true,
    "banner":null,
    "resouceLoader":null,
    "beanNameGenerator":null,
    "environment":null,
    "applicationContextClass":null,
    "webApplicationType":"SERVLET",
    "headless":true,
    "registerShutdownHook":true,
    "initializers":[
        org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer
        org.springframework.boot.context.ContextIdApplicationContextInitializer  
        org.springframework.boot.context.config.DelegatingApplicationContextInitializer  
        org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer      
        org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
    ],
    "listeners":[
        org.springframework.boot.ClearCachesApplicationListener
        org.springframework.boot.builder.ParentContextCloserApplicationListener
        org.springframework.boot.context.FileEncodingApplicationListener
        org.springframework.boot.context.config.AnsiOutputApplicationListener
        org.springframework.boot.context.config.ConfigFileApplicationListener
        org.springframework.boot.context.config.DelegatingApplicationListener
        org.springframework.boot.context.logging.ClasspathLoggingApplicationListener
        org.springframework.boot.context.logging.LoggingApplicationListener
        org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
        org.springframework.boot.autoconfigure.BackgroundPreinitializer
    ],
    "defaultProperties":null,
    "additionalProfiles":[],
    "allowBeanDefinitionOverriding":false,
    "isCustomEnvironment":false
}

SpringFactoriesLoader缓存的数据

{
    "org.springframework.boot.diagnostics.FailureAnalyzer": [
        "org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer", 
        "org.springframework.boot.diagnostics.analyzer.BeanDefinitionOverrideFailureAnalyzer", 
        "org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer", 
        "org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer", 
        "org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer", 
        "org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer", 
        "org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer", 
        "org.springframework.boot.diagnostics.analyzer.NoSuchMethodFailureAnalyzer", 
        "org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer", 
        "org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer", 
        "org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer", 
        "org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer", 
        "org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer", 
        "org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer", 
        "org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer", 
        "org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer", 
        "org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer"
    ], 
    "org.springframework.boot.env.EnvironmentPostProcessor": [
        "org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor", 
        "org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor", 
        "org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor"
    ], 
    "org.springframework.boot.SpringApplicationRunListener": [
        "org.springframework.boot.context.event.EventPublishingRunListener"
    ], 
    "org.springframework.context.ApplicationContextInitializer": [
        "org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer", 
        "org.springframework.boot.context.ContextIdApplicationContextInitializer", 
        "org.springframework.boot.context.config.DelegatingApplicationContextInitializer", 
        "org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer", 
        "org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer", 
        "org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener"
    ], 
    "org.springframework.boot.env.PropertySourceLoader": [
        "org.springframework.boot.env.PropertiesPropertySourceLoader", 
        "org.springframework.boot.env.YamlPropertySourceLoader"
    ], 
    "org.springframework.context.ApplicationListener": [
        "org.springframework.boot.ClearCachesApplicationListener", 
        "org.springframework.boot.builder.ParentContextCloserApplicationListener", 
        "org.springframework.boot.context.FileEncodingApplicationListener", 
        "org.springframework.boot.context.config.AnsiOutputApplicationListener", 
        "org.springframework.boot.context.config.ConfigFileApplicationListener", 
        "org.springframework.boot.context.config.DelegatingApplicationListener", 
        "org.springframework.boot.context.logging.ClasspathLoggingApplicationListener", 
        "org.springframework.boot.context.logging.LoggingApplicationListener", 
        "org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener", 
        "org.springframework.boot.autoconfigure.BackgroundPreinitializer"
    ], 
    "org.springframework.boot.diagnostics.FailureAnalysisReporter": [
        "org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter"
    ], 
    "org.springframework.boot.SpringBootExceptionReporter": [
        "org.springframework.boot.diagnostics.FailureAnalyzers"
    ], 
    "org.springframework.boot.autoconfigure.AutoConfigurationImportFilter": [
        "org.springframework.boot.autoconfigure.condition.OnBeanCondition", 
        "org.springframework.boot.autoconfigure.condition.OnClassCondition", 
        "org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition"
    ], 
    "org.springframework.boot.autoconfigure.AutoConfigurationImportListener": [
        "org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener"
    ], 
    "org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider": [
        "org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider", 
        "org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider", 
        "org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider", 
        "org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider", 
        "org.springframework.boot.autoconfigure.web.servlet.JspTemplateAvailabilityProvider"
    ], 
    "org.springframework.boot.autoconfigure.EnableAutoConfiguration": [
        "org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration", 
        "org.springframework.boot.autoconfigure.aop.AopAutoConfiguration", 
        "org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration", 
        "org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration", 
        "org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration", 
        "org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration", 
        "org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration", 
        "org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration", 
        "org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration", 
        "org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration", 
        "org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration", 
        "org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration", 
        "org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration", 
        "org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration", 
        "org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration", 
        "org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration", 
        "org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration", 
        "org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration", 
        "org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration", 
        "org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration", 
        "org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration", 
        "org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration", 
        "org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration", 
        "org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration", 
        "org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration", 
        "org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration", 
        "org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration", 
        "org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration", 
        "org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration", 
        "org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration", 
        "org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration", 
        "org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration", 
        "org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration", 
        "org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration", 
        "org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration", 
        "org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration", 
        "org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration", 
        "org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration", 
        "org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration", 
        "org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration", 
        "org.springframework.boot.autoconfigure.reactor.core.ReactorCoreAutoConfiguration", 
        "org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration", 
        "org.springframework.boot.autoconfigure.security.servlet.SecurityRequestMatcherProviderAutoConfiguration", 
        "org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration", 
        "org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration", 
        "org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration", 
        "org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration", 
        "org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration", 
        "org.springframework.boot.autoconfigure.session.SessionAutoConfiguration", 
        "org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration", 
        "org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration", 
        "org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration", 
        "org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration", 
        "org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration", 
        "org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration", 
        "org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration", 
        "org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration", 
        "org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration", 
        "org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration", 
        "org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration", 
        "org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration", 
        "org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration", 
        "org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration", 
        "org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration", 
        "org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration", 
        "org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration", 
        "tk.mybatis.mapper.autoconfigure.MapperAutoConfiguration"
    ], 
    "org.springframework.beans.BeanInfoFactory": [
        "org.springframework.beans.ExtendedBeanInfoFactory"
    ]
}

 

5. 总结

到此, SpringApplication的实例化过程到此结束, 整个流程共计4步,

  1. 调用WebApplicationType.deduceFromClasspath方法, 获取Web类型
  2. 通过getSpringFactoriesInstances()方法, 调用SpringFactoriesLoader.loadFactoryNames,首先META-INF/spring.factories加载到缓存中, 之后实例化了ApplicationContextInitializer的子类列表,赋值给this.initializers
  3. 通过getSpringFactoriesInstances()方法,调用SpringFactoriesLoader.loadFactoryNames,从SpringFactoriesLoader的缓存中获取并实例化ApplicationListener子类列表,赋值给this.listeners
  4. 通过抛出一个RuntimeException, 遍历其堆栈信息, 获取到类名中包含main方法的类, 实例化这个类, 赋值给this.mainApplicationClass
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值