深入Springboot启动流程+自动配置原理

深入Springboot启动流程+自动配置原理

  • 写在前面
    • 相关常见面试题
  • 1.Springboot启动类
    • 1.1.@SpringBootConfiguration解读
    • 1.2.@ComponentScan解读
    • 1.3.@EnableAutoConfiguration解读(重点)
      • 1.3.1.@AutoConfigurationPackage解读
      • 1.3.2.@Import({AutoConfigurationImportSelector.class})解读(重点)
    • 1.4.提问!自动配置到底配置了些什么东西呢?
      • 1.4.1.Spring中配置SpringMVC
      • 1.4.2.SpringBoot中的SpringMVC配置
  • 2.Springboot怎么启动TomCat的

深入Springboot启动流程+自动配置原理_第1张图片

写在前面

自从SpringBoot问世以来,开发界可以说是乱了套。
我还记得我朋友几年前去参加的JAVA培训班,培训半年时间,让你可以上手做简单的JAVA系统开发。同学里有做厨师的,有做理发师的,有链家的。大家都一股脑地想挤进IT行业。

这样没什么问题,行业的选择是每个人的权力。但造成了市场上初级程序员的大量过剩,薪资被庞大的人才供给迅速拉低,经的老牌程序员前辈被薪资倒挂。 为什么呢?要怪就怪SpringBoot。可以这么说,有了SpringBoot,初中生都能做JAVA开发。从此大量的人就开始了灰头土脸的初级程序员开发之路,埋着头往前走。

为什么要说这些呢? 有人说 ”看什么源码,学什么Spring,还不是做的增删改查,Spring只是一个工具嘛,会用就行了。“。 如果你也这么想,那么你可以右上角退出此文章了。

我说了那么多,就是想说给和我有共同志向的朋友,怎么样在当前恶劣的行业和就业环境中脱颖而出,怎么样让自己和家人过上好一点哪怕是好一点点的生活,怎么样在35岁时依然能够平步青云。

希望我的分享能够帮到和我一样在路上迷茫却不言弃的人,这篇文章建议收藏后慢慢阅读,一次性是肯定看不懂的,最好自己打开Idea一步一步跟进去看。

相关常见面试题

  1. 说说SpringBooot中IOC的原理。
  2. SpringBoot怎么实现自动装配的,什么是自动装配。
  3. SpringBoot是怎么启动TomCat的。
  4. 说说SpringBoot启动的时候做了什么。
    。。。

这些问题的答案在这篇文章结束的时候都会浮出水面。

1.Springboot启动类

我们发现,这个启动类最主要的做的事情分两个:

  1. 打了一个注解:@SpringBootApplication
  2. SpringApplication.run()方法启动主程序。

我们这里先从@SpringBootApplication注解开始分析

@SpringBootApplication
public class EsApplication {

    public static void main(String[] args) {
         SpringApplication.run(EsApplication.class, args);
    }

}

重点就在@SpringBootApplication注解中,我们点击进去会发现,@SpringBootApplication是一个复合注解。
深入Springboot启动流程+自动配置原理_第2张图片
其中包含3个比较重要的注解:

  1. @SpringBootConfiguration
  2. @ComponentScan
  3. @EnableAutoConfiguration

1.1.@SpringBootConfiguration解读

话不多说,我们直接进入这个注解内部去看看:
深入Springboot启动流程+自动配置原理_第3张图片
我们看到,@SpringBootConfiguration依然是一个复合注解,其中比较重要的是大家很熟悉的@Configuration注解。
那么,我们能够猜想到,@SpringBootConfiguration底层其实是@Configuration,那么@SpringBootConfiguration作用就是表明当前的Spring启动类(这里是EsApplication )是一个配置类,并且纳入Spring的管理

1.2.@ComponentScan解读

@ComponentScan注解我们这里就不多阐述,熟悉的朋友都知道,这个注解就是表明当前SpringBoot项目启动的时候,要去扫描哪些路径下的文件

1.3.@EnableAutoConfiguration解读(重点)

前两个注解好像不痛不痒,那么Spring Boot的核心到底在哪儿呢?
接下来要开始烧脑解读了。
我们看到了@EnableAutoConfiguration,顾名思义,这个注解叫”开启自动配置“。好,现在好像离我们的主题越来越近了。我们点进这个注解一看!
在这里插入图片描述
原来它也是一个复合注解,其中包含两个非常重要的子注解:

  1. @AutoConfigurationPackage
  2. @Import({AutoConfigurationImportSelector.class})

1.3.1.@AutoConfigurationPackage解读

见名知义, @AutoConfigurationPackage:自动配置包。
啊? 什么意思?什么是自动配置包?

我们进入此注解一看!
在这里插入图片描述
老朋友@Import出现了,关于@Import注解可以看看这篇文章:白话@Import注解.
这里就过多介绍了,简单来说就是通过@Import注解将一些目标的对象加入到IOC容器纳入Spring的管理。

我们看到@Import({Registrar.class}),所以这里我们要进入Registrar类去看看它做了什么,这里到底加了什么东西到Spring里去?

    static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
        Registrar() {
        }

        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
        }
    }

原来Registrar是一个静态类,提供了一个方法:

  1. registerBeanDefinitions:注册Bean

这个方法做了什么事情呢? 我们打个断点在这里,然后Debug模式启动SpringBoot应用。
深入Springboot启动流程+自动配置原理_第4张图片
好!我们看到传了两个参数:

  1. metadata:注解元信息,这里代表的就是@AutoConfigurationPackage所在类的类的信息,所以可以看到metadata的值是”com.example.es.EsApplication“(启动类),因为@AutoConfigurationPackage@EnableAutoConfiguration的子注解,所以可以看作@AutoConfigurationPackage是直接作用在我们的启动类EsApplication上的。

  2. registry:注册器

这里
这里可以看到,通过拿到注解元信息(com.example.es.EsApplication),通过getPackageNames方法,拿到启动类所在包的信息(com.example.es),然后把包信息放在一个String数组中返回。再配合@Import注解!一句话:

@AutoConfigurationPackage注解的作用就是找到主启动类所在的包,并把该包下的所有组件批量加载进Spring的管理!

这也能够解释了,为什么工作中我们的主启动类一定要放在根目录下,因为这样才能扫描到该项目所有目录的类信息。否则只能用@ComponentScan去手动的扫描目标路径。

1.3.2.@Import({AutoConfigurationImportSelector.class})解读(重点)

这里我们不是去探究@Import注解是什么含义,关于@Import注解可以看看这篇文章:白话@Import注解.

我们要讨论的是@Import({AutoConfigurationImportSelector.class})这个注解做了什么事情。
AutoConfigurationImportSelector这个类里面干了啥?

我们知道,@Import()注解如果是以selector方式做批量注入的话,那么必须继承ImportSelector类并重写selectImports方法。selectImports方法返回String数组,包含所有将要注入的类的全类名!不懂就去看这里:白话@Import注解.

好,我们进入AutoConfigurationImportSelector类,看看他到底做了什么动作。

深入Springboot启动流程+自动配置原理_第5张图片
可以看到,调用了getAutoConfigurationEntry()方法返回了将要注册进容器的数据。然后通过StringUtils.toStringArray()返回String数组。这个数组里就包含了所有自动配置类的全类名信息。

我们去到getAutoConfigurationEntry()方法中看看:

深入Springboot启动流程+自动配置原理_第6张图片
红框中的部分是重要部分,返回了一个List,List的名称叫configurations,顾名思义:调用getCandidateConfigurations()方法,返回了一个配置类全类名集合。

绿框中的部分我们不深入探究,大概就是对configurations集合做一些去重操作。

所以我们现在继续进入getCandidateConfigurations()方法,看看到底在启动SpringBoot项目的时候,自动配置了哪些类呢?

在这里插入图片描述
这里通过SpringFactoriesLoader类中的loadFactoryNames()方法获取目标数据。所以我们继续深入:
深入Springboot启动流程+自动配置原理_第7张图片
继续调用了loadSpringFactories()方法:
深入Springboot启动流程+自动配置原理_第8张图片
好!
到底了!
我们来分析一下这里做了什么事情呢?

这里的代码很长,很难看懂。我们只关注红框中的代码:
Enumeration urls = classLoader.getResources(“META-INF/spring.factories”);

什么意思呢?
去我们的依赖包里,找到META-INF文件夹下,spring.factories文件,把文件中的信息读取到我们程序中来:
深入Springboot启动流程+自动配置原理_第9张图片
我们浏览Spring相关的依赖包,发现并不是所有包里都有META-INF/spring.factories文件。
但我们要清楚,我们这里是SpringBoot启动时的自动配置功能,所以我们去找到:
深入Springboot启动流程+自动配置原理_第10张图片
打开spring.factories搂一眼:

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.autoconfigure.BackgroundPreinitializer

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.autoconfigure.integration.IntegrationPropertiesEnvironmentPostProcessor

# Auto Configuration Import Listeners
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

# Auto Configure
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.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
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.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
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.Neo4jReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
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.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
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.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
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.neo4j.Neo4jAutoConfiguration,\
org.springframework.boot.autoconfigure.netty.NettyAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
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.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
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.sql.init.SqlInitializationAutoConfiguration,\
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.ReactiveMultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebSessionIdResolverAutoConfiguration,\
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

# Failure analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.autoconfigure.data.redis.RedisUrlSyntaxFailureAnalyzer,\
org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
org.springframework.boot.autoconfigure.flyway.FlywayMigrationScriptMissingFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer,\
org.springframework.boot.autoconfigure.jooq.NoDslContextBeanFailureAnalyzer,\
org.springframework.boot.autoconfigure.r2dbc.ConnectionFactoryBeanCreationFailureAnalyzer,\
org.springframework.boot.autoconfigure.r2dbc.MissingR2dbcPoolDependencyFailureAnalyzer,\
org.springframework.boot.autoconfigure.r2dbc.MultipleConnectionPoolConfigurationsFailureAnalzyer,\
org.springframework.boot.autoconfigure.r2dbc.NoConnectionFactoryBeanFailureAnalyzer,\
org.springframework.boot.autoconfigure.session.NonUniqueSessionRepositoryFailureAnalyzer

# Template availability providers
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

# DataSource initializer detectors
org.springframework.boot.sql.init.dependency.DatabaseInitializerDetector=\
org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializerDatabaseInitializerDetector

# Depends on database initialization detectors
org.springframework.boot.sql.init.dependency.DependsOnDatabaseInitializationDetector=\
org.springframework.boot.autoconfigure.batch.JobRepositoryDependsOnDatabaseInitializationDetector,\
org.springframework.boot.autoconfigure.quartz.SchedulerDependsOnDatabaseInitializationDetector,\
org.springframework.boot.autoconfigure.session.JdbcIndexedSessionRepositoryDependsOnDatabaseInitializationDetector

我们发现,这个文件就是一批类的全类名,SpringBoot启动的时候,会读取到这个文件,将文件中
深入Springboot启动流程+自动配置原理_第11张图片
Auto Configure注释下的所有类名读取到程序中,并将这些类加载进容器!
细心的同学可以看到了,
深入Springboot启动流程+自动配置原理_第12张图片

这些类全部都是AutoConfiguration结尾的,顾名思义,这些类就是我们要找的自动配置类!

那么回到最开始:
@SpringBootApplication注解中的@EnableAutoConfiguration注解中的
@Import({AutoConfigurationImportSelector.class}) 做了什么事情呢?

通过SpringFactoriesLoader,找到依赖包中META-INF/spring.factories文件,将文件中的自动配置类找出来,加载进内存!


1.4.提问!自动配置到底配置了些什么东西呢?

深入Springboot启动流程+自动配置原理_第13张图片

我们现在知道了,SpringBoot项目启动是,通过@EnableAutoConfiguration注解,会把一批自动配置类加载进容器,那到底配置了些啥?为什么非要配置这些东西呢?

对于一个用SpringBoot用久的人来说,确实搞不清这个问题了。
那我们先回忆一下
以前用Spring的时候,如果我们要在Spring中使用SpringMVC该做什么事呢?
有没有唤起你一点尘封的回忆呢?

1.4.1.Spring中配置SpringMVC

在Spring中,我们首先要定义:spring-mvc.xml作为SpringMVC的配置文件。配置包括(编解码、静态资源路径、图解析器、请求拦截器等等):
例如:


<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
          http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
	
    
    <mvc:annotation-driven>
        
        <mvc:message-converters register-defaults="true">
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
              	<constructor-arg index="0" value="UTF-8"/>
            bean>
        mvc:message-converters>
	 mvc:annotation-driven>
 
	
	<context:component-scan base-package="com.bruce.user.controller">
			<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
	context:component-scan>
	
  
	<mvc:resources location="/WEB-INF/views/static/" mapping="/static/**" />
    
	
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="order" value="1"/>
		<property name="prefix" value="/WEB-INF/views/"/>
		<property name="suffix" value=".jsp"/>
	bean>
 
  
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
	
  
	<bean class="com.bruce.user.SwaggerConfig" />
	<mvc:resources mapping="/swagger/**" location="/WEB-INF/swagger/" />
	
  
	<mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/api/user/**"/>
			      <mvc:exclude-mapping path="/api/skip/**"/>
            <bean class="com.bruce.common.interceptor.LoginInterceptor"/>
        mvc:interceptor>
	mvc:interceptors>
	
beans>

然后再web.xml中注册MVC的配置文件路径,指明DispatcherServlet。
例如:


   
	 <servlet>
	   <servlet-name>mvcservlet-name>
	   <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>    
     
	   <init-param>
	     <param-name>contextConfigLocationparam-name>
	     <param-value>classpath:context/spring-mvc.xmlparam-value>
	   init-param>
     
	   <load-on-startup>1load-on-startup>
	 servlet>

1.4.2.SpringBoot中的SpringMVC配置

而SpringBooot中我们发现根本就没有那么多麻烦的配置。那么它是怎么做到的呢?

我们去META-INF/spring.factories文件中找到这一行:
深入Springboot启动流程+自动配置原理_第14张图片
顾名思义了,WebMvcAutoConfiguration,MVC自动配置类,我们点击进去看看这个类做了什么事情:
深入Springboot启动流程+自动配置原理_第15张图片
好。我们看到这里有三个比较值得一提的注解:

  1. @ConditionalOnClass(xxxx):
    条件注解,表示当前WebMvcAutoConfiguration类要加载进内存的话,必须满足当前容器中存在Servlet、DispatcherServlet、WebMvcConfigurer这三个类。
    当前我们引入的依赖是:
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>

所以Servlet、DispatcherServlet、WebMvcConfigurer这三个类是肯定存在的。条件判断通过。

  1. @ConditionalOnMissingBean(xxxx):
    条件注解,表示当前容器中必须没有WebMvcConfigurationSupport这个类,当前WebMvcAutoConfiguration才能加载进内存。
    WebMvcConfigurationSupport是Spring中需要的类,SpringBooot并不需要这个类,因此条件判断通过。

  2. @AutoConfigureAfter(xxxx):
    执行顺序注解,表示当前WebMvcAutoConfiguration这个类如果想开始自动配置,那么就必须在DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class这三个类存在之后再开始执行!
    而其中比较重要的是DispatcherServletAutoConfiguration.class

所以我们要先去DispatcherServletAutoConfiguration.class这个类看看它做了是什么事情,而我们同时也发现在META-INF/spring.factories文件中,也存在这个类
在这里插入图片描述
好!
我们继续,进入DispatcherServletAutoConfiguration。
不过我们这里稍微停一下,让我们先回忆一下什么是DispatcherServlet。

在这里插入图片描述
所以,对于SpringMVC而言,DispatcherServlet是十分重要的一个组件。

深入Springboot启动流程+自动配置原理_第16张图片
我截取的这个类最重要的一段代码:
DispatcherServletConfiguration这个静态内部类。

这个静态内部类中,有两个方法:

  1. dispatcherServlet():返回一个DispatcherServlet对象,并将其加载进容器!SpringBoot在这里帮我们默认地创建好,就不需要像Spring中自己去写Web.xml。
  2. multipartResolver():返回一个MultipartResolver对象,并将其加载进容器!这个东西是管理文件上传的,SpringBoot默认帮我们创建好。

深入Springboot启动流程+自动配置原理_第17张图片
我们看到创建dispatcherServlet对象时,用到了WebMvcProperties对象,这个对象从哪儿来的呢?
加下来就要看到这个非常重要的注解了:@EnableConfigurationProperties

@EnableConfigurationProperties:从配置文件中(这里指的是application.properties/yml),取到对应的数据,封装在WebMvcProperties中并使用

我们点击进入WebMvcProperties.class:
深入Springboot启动流程+自动配置原理_第18张图片
这个注解熟悉吧:
@ConfigurationProperties:从配置文件中(这里指的是application.properties/yml),取到对应的数据,封装在WebMvcProperties中。那么配置文件那么多东西,我这里要取哪些东西呢?

prefix = “spring.mvc”:取前缀是spring.mvc的数据!

例如:
深入Springboot启动流程+自动配置原理_第19张图片

好,现在大家应该清楚了,我们平时在application.properties中配置的东西是怎么加载进对象了的吧。就是这么直接简单粗暴。

好了,
现在DispatcherServletAutoConfiguration配置类配置完成,就可以开始WebMvcAutoConfiguration的自动配置了。 这里就不多介绍了,大体的原理和前面描述的差不多。

现在大概应该明白了SpringBoot的自动配置配置了哪些东西了。


2.Springboot怎么启动TomCat的

深入Springboot启动流程+自动配置原理_第20张图片
这是中高级工程师面试中常问的问题。
知道现在有多卷了吧!
我记得我刚找工作那会儿,我只要8000的工资,面试官都要问这个问题。我真TM的醉了!

我的另一篇文章:深入springboot怎么启动tomcat.


你的点赞收藏是我分享的动力,谢谢。

你可能感兴趣的