Springboot2.6.x的启动流程与自动配置详解

目录
  • 一、Springboot启动流程
  • 1. 第一步对SpringApplication的初始化
    • 2. 第二步SpringApplication具体的启动方案
    • 3、refreshContext:核心启动tomcat流程
  • 二、Springboot自动配置原理
    • 1. @SpringBootApplication
    • 2自动配置流程
    • 3、额外注解学习
  • 总结

一、Springboot启动流程

所有的SpringBoot工程,都有自己的启动类,这个启动类身上有一个固定注解@SpringBootApplication,并携带一个main(),通过这个方法即可完成启动。

启动流程,可以分为2个步骤:

1、初始化SpringApplication对象阶段 (加载相关资源,判断是否是个WEB工程,创建一个构造器(完成自动化配置),创建一个ContextLoadLister,加载主启动类所需要所有组件)

2、run启动应用阶段

​ 开启各种容器:tomcat容器,springIOC容器(DispatchServlet,ContextLoaderListener),向各种容器加载组件,并配置容器之间上下文环境

1. 第一步对SpringApplication的初始化

Springboot启动类入口程序,SpringApplication.run方法,先看run方法,再看@SpringBootApplication注解实现的自动配置功能。

run方法点击后,进入源码,如下图所示,会发现最终第二步源码中,实例化了SpringApplication,同时也运行了run方法。

先看SpringApplication的构造方法:它干了什么事情!

代码如下:

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    // resourceLoader 属性注入了 null
   this.resourceLoader = resourceLoader;
   Assert.notNull(primarySources, "PrimarySources must not be null");
  // 将启动类从数组重新封装成了 Set,注入到 primarySources 属性
   this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    // 得到 web应用的类型,这里是 SERVLET
    /*
    webApplicationType 有三种类型,REACTIVE、SERVLET、NONE
	引入 spring-boot-starter-web 包,就是 SERVLET
	引入 spring-boot-starter-webflux 包,是 REACTIVE
	都没有就是 NONE
    */
   this.webApplicationType = WebApplicationType.deduceFromClasspath();
    //从 META-INF/spring.factories
    //文件中得到 key 为 org.springframework.boot.BootstrapRegistryInitializer 的全类名集合,进行实例化,然后注入 bootstrapRegistryInitializers 属性
    //其中核心方法getSpringFactoriesInstances,等会详细讲解
   this.bootstrapRegistryInitializers = new ArrayList<>(
         getSpringFactoriesInstances(BootstrapRegistryInitializer.class));

//这一行代码,只是封装了一下,仍然还是调用 getSpringFactoriesInstances 方法,
//从 META-INF/spring.factories 文件中得到 key 为org.springframework.context.ApplicationContextInitializer 的全类名集合,
//进行实例化,然后注入 initializers(初始化器集合) 属性。
    setInitializers((Collection)   getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 同理,得到监听器实例的集合,并注入  简单解释getSpringFactoriesInstances就是去spring.factories中读取配置文件
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    // 获取当前运行的 main 方法所在的类,也就是咱们的主类
   this.mainApplicationClass = deduceMainApplicationClass();
}

上述的META-INF/spring.factories 文件,都是在spring-boot.jar包中。

完成了第一步对SpringApplication的初始化模块,配置一些基本的环境变量、资源、构造器、监听器

提示:第一步操作,getSpringFactoriesInstances方法中,有一个核心实例化类是SpringFactoriesLoader类和createSpringFactoriesInstances方法:具体内容后面讲解。

2. 第二步SpringApplication具体的启动方案

完成SpringApplication的初始化以后,将继续运行run方法,对启动流程的监听模块、加载配置环境模块、及核心的创建上下文环境模块进行加载。

回到构造方法下,进行第二步代码跟进:

run方法代码有点长,截取重点解释:忽略了所有的catch方法。

/**
运行 Spring 应用程序,创建并刷新一个新的ApplicationContext 。
参数:
args – 应用程序参数(通常从 Java 主方法传递)
回报:
正在运行的ApplicationContext
**/
public ConfigurableApplicationContext run(String... args) {
   long startTime = System.nanoTime();
    // 添加了一个默认的 Bootstrap 上下文,
    //查看createBootstrapContext代码,就是 new 了一个 DefaultBootstrapContext 实例,然后遍历初始化了 bootstrapRegistryInitializers 中的所有初始化器
//bootstrapRegistryInitializers在第一步讲解的属性,实例化 SpringApplication 时通过 getSpringFactoriesInstances 方法获得并注入的。
   DefaultBootstrapContext bootstrapContext = createBootstrapContext();
   ConfigurableApplicationContext context = null;
    // 配置Headless属性 无头模式,不用了解
    //此处调用的是:java.awt.headless
    //不提供外部设备的情况,自行运算
   configureHeadlessProperty();
    // 获得 RunListener 集合类 这里我们又看到了熟悉的 getSpringFactoriesInstances,
    //这次的 key 是 org.springframework.boot.SpringApplicationRunListener 这里会得到 EventPublishingRunListener 对象
   SpringApplicationRunListeners listeners = getRunListeners(args);
    // 循环启动这些监听器 通过广播模式 得到应用监听器后,循环调用监听器的 onApplicationEvent方法,具体源码先跳过
    //如果要跟源码 请参考:starting-->listener.starting(bootstrapContext) -->initialMulticaster.multicastEvent -->invokeListener(listener, event) -->doInvokeListener--->listener.onApplicationEvent(event)  结束
   listeners.starting(bootstrapContext, this.mainApplicationClass);
   try {
       // 封装参数
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
       // 创建并配置环境 第一步读取并实例化的3个配置:
       //点击prepareEnvironment方法进入源码:prepareEnvironment-->1.getOrCreateEnvironment(配置web环境)-->同级
       //2.listeners.environmentPrepared(bootstrapContext, environment)比较重要,下方截图讲解:它包含了环境配置的处理以及yml文件的读取
      ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
      //配置yml中配置的需忽略的bean的环境信息
      configureIgnoreBeanInfo(environment);
       打印 Banner  就是启动的时候那个Springboot图标
      Banner printedBanner = printBanner(environment);
       // 实例化上下文对象,因为类型是 SERVLET,所以实例化的是 AnnotationConfigServletWebServerApplicationContext 对象
      context = createApplicationContext();
      context.setApplicationStartup(this.applicationStartup);
       // 准备上下文,以及实例化bean对象
      prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
       // 刷新上下文:进refreshContext进入,主要逻辑在 AbstractApplicationContext 对象的 refresh 方法中。
       //该方法中有一个方法是onRefresh(),它内部就是创建tomcat的:核心方法是ServletWebServerApplicationContext.createWebServer方法,该方法中的this.webServer = factory.getWebServer(getSelfInitializer());
       //getWebServer内部实现类TomcatServletWebServerFactory将会创建tomcat!
       //但是还没有启动tomcat;AbstractApplicationContext.refresh最后一个方法finishRefresh();中将会启动tomcat!
       // 请参考下方单独提出的tomcat启动相关
      refreshContext(context);
       //空方法 啥都没有
      afterRefresh(context, applicationArguments);
       // 计算耗时
      Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
       //日志打印 不用看
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
      }
        // 监听器执行 started 方法,表示启动成功
      listeners.started(context, timeTakenToStartup);
       // 回调所有的ApplicationRunner和CommandLineRunner
      callRunners(context, applicationArguments);
   }
    try {
			Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
         // 监听器执行 ready 方法
			listeners.ready(context, timeTakenToReady);
		}
   return context;
}

重点还是 refreshContext(context);方法:单独提出来。

3、refreshContext:核心启动tomcat流程

主要逻辑在 AbstractApplicationContext 对象的 refresh 方法中:上文有一定的描述。具体截图如下,忽略其他业务情况下。

找到核心的抽象类实现:ServletWebServerApplicationContext

createWebServer方法下,将创建tomcat。

继续往下,点击getWebServer方法:

找到tomcat服务工厂:

tomcat被new出来了,此时回到入口处:

入口处:

继续往下:

进入实现类DefaultLifecycleProcessor中,通过startBeans继续往下:

继续往下:

看见do开头的方法了,已经到了真正代码实现的地方了,继续往下

继续进入doStart方法:

进入start方法:

进入WebServerStartStopLifecycle的start实现中:

再次继续进入:

在web服务启动中,找到Tomcat的启动实现:

最终完成启动,看见了Tomcat的启动过程,不过volatile不懂的,这个地方也不好解释,请自行研究JMM:

## 3. 总结

1)实例化 SpringApplication 对象

2)通过spring.factories 得到 初始化BootstrapRegistryInitializer、ApplicationContextInitializer 和 监听器ApplicationListener

3)调用 run 方法

4)记录开始时间

5)得到 runListeners

6)runListeners 执行 starting

7)准备环境

8)打印 banner

9)实例化上下文对象

10)准备上下文,执行之前得到的初始化器的初始化方法,load主bean

11)刷新上下文,在其中加载 autoConfiguration,并启动 Tomcat

12)计算耗时

13)打印耗时

14)通知监听器启动完成

15)通知监听器 ready

4. 补充 getSpringFactoriesInstances

在第一步SpringApplication实例化的时候:3个getSpringFactoriesInstances方法的详细解析!

随便点击一个进入:

这里面比较关键的逻辑是 得到类的全类名集合 和 实例化类,第一个红框下
SpringFactoriesLoader.loadFactoryNames(type, classLoader)该方法下:

loadSpringFactories方法中:

从这些代码我们可以得知,会从 spring-boot.jar下的META-INF/spring.factories 文件中找到 key 匹配的类,并把类的全路径集合得到;

回到之前第二个红框下:如下图

例如实例化 SpringApplication 对象时,获得 初始化器 和 监听器:

之后通过全类名,使用反射技术,实例化类,最终得到想要的集合

二、Springboot自动配置原理

1. @SpringBootApplication

该注解为启动注解,注解结构是:

作用:

1、完成容器的自动扫描 @ComponentScan

2、完成自动配置@EnableAutoConfiguration

3、加载配置类@SpringBootConfiguration

页面:不推荐使用JSP,相反:Freemarker,Thymeleaf这页面技术(模板引擎:JSTL)

2自动配置流程

1)、SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration

2)、@EnableAutoConfiguration 作用:

利用EnableAutoConfigurationImportSelector给容器中导入一些组件?

可以查看selectImports()方法的内容,其中核心代码getAutoConfigurationEntry;

在AutoConfigurationImportSelector的getAutoConfigurationEntry方法中:List configurations = getCandidateConfigurations(annotationMetadata, attributes);获取候选的配置:debug截图!

在getCandidateConfigurations方法中,SpringFactoriesLoader.loadFactoryNames()核心方法:

继续进入loadFactoryNames()方法,这个方法会扫描所有jar包类路径下 META-INF/spring.factories:

进入loadSpringFactories方法中,获取到常量配置META-INF/spring.factories:

上图所示:把扫描到的这些文件的内容包装成properties对象,从properties中获取到key为EnableAutoConfiguration.class类(全限定类名)对应的值,然后把他们添加在容器中。

将类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到了容器中;

可以去依赖包中,spring-boot-autoconfigure中,找到META-INF下的spring.factories,部分代码如下:

# 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

每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;

3)、每一个自动配置类进行自动配置功能;

4)、以**HttpEncodingAutoConfiguration(Http编码自动配置)**为例解释自动配置原理;

@Configuration(proxyBeanMethods = false)  //表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件
@EnableConfigurationProperties(ServerProperties.class) //启动指定类的ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来;并把HttpEncodingProperties加入到ioc容器中

@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)//Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果满足指定的条件,整个配置类里面的配置就会生效;    判断当前应用是否是web应用,如果是,当前配置类生效

@ConditionalOnClass(CharacterEncodingFilter.class)//判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;

@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
  //判断配置文件中是否存在某个配置  spring.http.encoding.enabled;如果不存在,判断也是成立的
//即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
public class HttpEncodingAutoConfiguration {

  	//他已经和SpringBoot的配置文件映射了
  	private final Encoding properties;

   //只有一个有参构造器的情况下,参数的值就会从容器中拿
  	public HttpEncodingAutoConfiguration(ServerProperties properties) {
		this.properties = properties.getServlet().getEncoding();
	}

    @Bean   //给容器中添加一个组件,这个组件的某些值需要从properties中获取
	@ConditionalOnMissingBean //判断容器没有这个组件?
	public CharacterEncodingFilter characterEncodingFilter() {
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE));
		return filter;
	}

根据当前不同的条件判断,决定这个配置类是否生效?

一但这个配置类生效;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的;

5)、所有在配置文件中能配置的属性都是在xxxxProperties类中封装者‘;配置文件能配置什么就可以参照某个功能对应的这个属性类

@ConfigurationProperties(prefix = "spring.http.encoding")  //从配置文件中获取指定的值和bean的属性进行绑定
public class HttpEncodingProperties {

   public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

精髓:

1)、SpringBoot启动会加载大量的自动配置类

2)、我们看我们需要的功能有没有SpringBoot默认写好的自动配置类;

3)、我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)

4)、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值;

xxxxAutoConfigurartion:自动配置类;

给容器中添加组件

xxxxProperties:封装配置文件中相关属性;

3、额外注解学习

1、@Conditional派生注解(Spring注解版原生的@Conditional作用)

作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;

@Conditional扩展注解 作用(判断是否满足当前指定条件)
@ConditionalOnJava 系统的java版本是否符合要求
@ConditionalOnBean 容器中存在指定Bean;
@ConditionalOnMissingBean 容器中不存在指定Bean;
@ConditionalOnExpression 满足SpEL表达式指定
@ConditionalOnClass 系统中有指定的类
@ConditionalOnMissingClass 系统中没有指定的类
@ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty 系统中指定的属性是否有指定的值
@ConditionalOnResource 类路径下是否存在指定资源文件
@ConditionalOnWebApplication 当前是web环境
@ConditionalOnNotWebApplication 当前不是web环境
@ConditionalOnJndi JNDI存在指定项

自动配置类必须在一定的条件下才能生效;

我们怎么知道哪些自动配置类生效;

我们可以通过启用 debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置类生效;

=========================
AUTO-CONFIGURATION REPORT
=========================

Positive matches:(自动配置类启用的)
-----------------

   DispatcherServletAutoConfiguration matched:
      - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)
      - @ConditionalOnWebApplication (required) found StandardServletEnvironment (OnWebApplicationCondition)

Negative matches:(没有启动,没有匹配成功的自动配置类)
-----------------

   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory', 'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)

   AopAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required classes 'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (OnClassCondition)

总结

到此这篇关于Springboot2.6.x启动流程与自动配置的文章就介绍到这了,更多相关Springboot2.6.x启动流程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot整个启动过程的分析

    前言 前一篇分析了SpringBoot如何启动以及内置web容器,这篇我们一起看一下SpringBoot的整个启动过程,废话不多说,正文开始. 正文 一.SpringBoot的启动类是**application,以注解@SpringBootApplication注明. @SpringBootApplication public class CmsApplication { public static void main(String[] args) { SpringApplication.run

  • springboot自动配置没有生效的问题定位(条件断点)

    Spring Boot在为开发人员提供更高层次的封装,进而提高开发效率的同时,也为出现问题时如何进行定位带来了一定复杂性与难度.但Spring Boot同时又提供了一些诊断工具来辅助开发与分析,如spring-boot-starter-actuator.本文分享一个基于actuator与IDEA条件断点来定位自动配置未生效的案例.望对类似问题分析与处理提供参考. 问题确认 在前文介绍的 Spring Boot从入门到实战:整合通用Mapper简化单表操作 中,我们对druid连接池做了自动配置,

  • Spring Boot启动过程完全解析(一)

    之前在排查一个线上问题时,不得不仔细跑了很多遍Spring Boot的代码,于是整理一下,我用的是1.4.3.RELEASE. 首先,普通的入口,这没什么好说的,我就随便贴贴代码了: SpringApplication.run(Application.class, args); --> public static ConfigurableApplicationContext run(Object source, String... args) { return run(new Object[]

  • SpringBoot应用启动过程分析

    SpringBoot项目通过SpringApplication.run(App.class, args)来启动: @Configuration public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } } 接下来,通过源码来看看SpringApplication.run()方法的执行过程.如果对源码不感兴趣,直接下拉到文章末尾,看启动框图. 1.调用S

  • SpringBoot自动配置的实现原理

    一.运行原理 Spring Boot的运行是由注解@EnableAutoConfiguration提供的. @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({EnableAutoConfigurationImportSelector.class}) public @interface EnableAuto

  • Spring Boot实战教程之自动配置详解

    前言 大家应该都有所了解,随着Ruby.Groovy等动态语言的流行,相比较之下Java的开发显得格外笨重.繁多的配置.低下的开发效率.复杂的部署流程以及第三方技术集成难度大等问题一直被人们所诟病.随着Spring家族中的新星Spring Boot的诞生,这些问题都在逐渐被解决. 个人觉得Spring Boot中最重要的两个优势就是可以使用starter简化依赖配置和Spring的自动配置.下面这篇文章将给大家详细介绍Spring Boot自动配置的相关内容,话不多说,来一起看看详细的介绍. 使

  • 全面解析SpringBoot自动配置的实现原理

    之前一直在用SpringBoot框架,一直感觉SpringBoot框架自动配置的功能很强大,但是并没有明白它是怎么实现自动配置的,现在有空研究了一下,大概明白了SpringBoot框架是怎么实现自动配置的功能,我们编写一个最简单的自动配置功能,大概的总结一下. 一,配置属性类 其实就是值对象注入的方式去配置一些Spring常用的配置,我们编写一个最简单的配置对象. @ConfigurationProperties(prefix = "hello") //@Component //如果这

  • Springboot2.6.x的启动流程与自动配置详解

    目录 一.Springboot启动流程 1. 第一步对SpringApplication的初始化 2. 第二步SpringApplication具体的启动方案 3.refreshContext:核心启动tomcat流程 二.Springboot自动配置原理 1. @SpringBootApplication 2自动配置流程 3.额外注解学习 总结 一.Springboot启动流程 所有的SpringBoot工程,都有自己的启动类,这个启动类身上有一个固定注解@SpringBootApplicat

  • Android开发App启动流程与消息机制详解

    目录 引言 1.第一步了解 ThreadLocal 2.App的启动流程 3.Activity中创建Handler 引言 相信很多人对这个问题不陌生,但是大家回答的都比较简单,如谈到app启动流程有人就会是app的生命周期去了,谈到消息机制有人就会说looper循环消息进行分发,如果是面试可能面试官不会满意,今天我们搞一篇完善的源码解析来进行阐述上面的问题 1.第一步了解 ThreadLocal 什么是ThreadLocal呢,专业的来讲,ThreadLocal 是一个线程内部的数据存储类,通过

  • Springboot @Configuration与自动配置详解

    不知道大家第一次搭SpringBoot环境的时候,有没有觉得非常简单.无须各种的配置文件,无须各种繁杂的pom坐标,一个main方法,就能run起来了.与其他框架整合也贼方便,使用EnableXXXXX注解就可以搞起来了! 所以今天来讲讲SpringBoot是如何实现自动配置的~ @SpringBootApplication: Spring Boot应用标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot需要运行这个类的main方法来启动SpringBoot应用: 先看

  • 通过Spring Boot整合Mybatis分析自动配置详解

    前言 SpringBoot凭借"约定大于配置"的理念,已经成为最流行的web开发框架,所以有必须对其进行深入的了解:本文通过整合Mybatis类来分析SpringBoot提供的自动配置(AutoConfigure)功能,在此之前首先看一个整合Mybatis的实例. SpringBoot整合Mybatis 提供SpringBoot整合Mybatis的实例,通过Mybatis实现简单的增删改查功能: 1.表数据 CREATE TABLE `role` ( `note` varchar(25

  • Yii2语言国际化自动配置详解

    如何实现语言国际自动化,大家可能觉得自动化,是不是不需要配置就自动切换,这个思路我之前也想过,能不能根据IP来判断地理位置然后确定其语言,网上找过一个"IpToCountry"相关的,有兴趣的可以搜索出来看看,他会提供一个ip对照的表,每隔一段时间会更新一次,不过这个暂时没做,后面考虑尝试下 这里我们说下Yii2如何实现,因为我们上面的一篇文章分享做了语言国际化的配置,也将对应的语言翻译了出来,下面就是需要根据条件来做切换 从配置文件我们知道只需要更改language这个配置值就可以了

  • SpringBoot2.1.x,创建自己的spring-boot-starter自动配置模块操作

    一)spring-boot-starter命名规则 自动配置模块命名规则:xxx-spring-boot,如:aspectlog-spring-boot 启动器命名规则:xxx-spring-boot-starter,如:aspectlog-spring-boot-starter 如两者只有一个模块:建议以xxx-spring-boot-starter方式命名. springboot建议以xxx前缀的方式对自己的自动配置命名的. 二)spring-boot-starter条件注解 注解 说明 @

  • Android usb设备权限查询及自动获取详解流程

    看到当上面的对话框弹出时,可以使用命令查看顶层的活动窗口 adb shell dumpsys window | findstr mCurrentFocus mCurrentFocus=Window{41ab0ee0 u0 com.android.systemui/com.android.systemui.usb.UsbPermissionActivity} 这就是应用的位置,当然我们也可以是用grep命令来查找这个对话框的.xml文件,进入android源码然后输入命令: grep '默认情况下

  • Springboot启动原理和自动配置原理解析

    目录 启动原理 SpringApplication 1.初始化 2.调用run方法 自动配置原理 放本地文件夹都快吃土了,准备清理文件夹,关于Springboot的! 启动原理 @SpringBootApplication public class Start { public static void main(String[] args) { SpringApplication.run(Start.class, args); } } SpringApplication 1.初始化 public

  • Spring Cloud Alibaba Nacos Config加载配置详解流程

    目录 1.加载节点 2.NacosPropertySourceLocator的注册 3.加载 3.1.加载share 3.2.加载extention 3.3.加载主配置文件 1.加载节点 SpringBoot启动时,会执行这个方法:SpringApplication#run,这个方法中会调prepareContext来准备上下文,这个方法中调用了applyInitializers方法来执行实现了ApplicationContextInitializer接口的类的initialize方法.其中包括

随机推荐