美文网首页源码解读
Spring源码1:初始化SpringApplication实例

Spring源码1:初始化SpringApplication实例

作者: ygxing | 来源:发表于2019-04-23 17:58 被阅读0次

    上篇回顾

    上一篇springboot启动流程以及源码剖析目录


    目录

    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

    下一篇

    我们将会在下一篇发布启动事件ApplicationStartingEvent, 继续研究springboot的启动流程

    相关文章

      网友评论

        本文标题:Spring源码1:初始化SpringApplication实例

        本文链接:https://www.haomeiwen.com/subject/tijbgqtx.html