Spring Boot 启动过程与自动配置详解:从源码到实现

在使用 Spring Boot 时,开发者常常会感到惊讶:为什么这么少的配置却能实现如此丰富的功能?为何启动一个 Spring Boot 应用可以变得如此简单便捷?在这个看似平凡的启动过程中,其实隐藏着一套精妙的自动化机制和源码逻辑。本文将带你深入探索 Spring Boot 的启动流程,逐步揭开自动配置的幕后奥秘。通过了解这些底层原理,你将发现,原来每一次应用的无缝启动都是精心设计的结果,让你对 Spring Boot 有更深刻的理解和掌控力!

一、整体概述

(一)基本整体初步分析

Spring Boot 是一个用于构建独立的、生产级的 Spring 应用程序的框架,它提供了自动化的配置和约定优于配置的原则。在理解 Spring Boot 的启动配置原理之前,我们需要了解几个关键概念。

首先,Spring Boot 使用了基于约定的自动配置机制。它通过在 classpath 下查找特定的配置文件和类,根据应用程序所使用的依赖自动配置 Spring 应用程序的各种组件。这样可以大大简化开发者的工作,减少了手动配置的需求。

其次,Spring Boot 使用了条件化配置(Conditional Configuration)的机制。这意味着配置的应用取决于一组条件是否满足。条件可以基于多种因素,如 classpath 中存在特定的类、特定的 bean 是否存在等等。通过条件化配置,Spring Boot 可以根据不同的环境和需求进行动态的配置。

Spring Boot 的启动配置原理可以概括如下:

  1. 在启动过程中,Spring Boot 会加载并解析应用程序的配置文件,其中包括 application.properties 或 application.yml 文件等。这些文件中可以定义各种属性和配置信息,如数据库连接、日志级别等。
  2. Spring Boot 会自动扫描 classpath 下的特定包,寻找带有特定注解的类,如 @SpringBootApplication。这个注解标识了一个 Spring Boot 应用程序的入口点。
  3. 根据配置文件中的属性和条件化配置的机制,Spring Boot 自动配置应用程序的各种组件,包括数据库连接池、消息队列、Web 服务器等。如果需要进行自定义配置,可以使用专门的注解或编写自定义的配置类。
  4. 在应用程序启动时,Spring Boot 会初始化 Spring 容器,并根据配置进行相应的初始化工作。这包括创建和管理 bean、处理依赖注入等。

总的来说,Spring Boot 的启动配置原理是基于自动化的约定和条件化配置机制。它通过读取配置文件、扫描注解、自动配置组件等步骤,简化了应用程序的配置过程,并提供了灵活性和易用性。

(二)从启动来看整体过程图分析

每个SpringBoot程序都有一个主入口main方法,main里面调用SpringApplication.run()启动整个SpringBoot程序,该方法所在类需要使用@SpringBootApplication注解,例如如下

 
  1. package org.zyf.javabasic;
  2.  
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. import org.springframework.context.ApplicationContext;
  6. import org.springframework.context.annotation.ComponentScan;
  7. import org.springframework.context.annotation.EnableAspectJAutoProxy;
  8. import springfox.documentation.swagger2.annotations.EnableSwagger2;
  9.  
  10. /**
  11. * 描述:启动入口类
  12. *
  13. * @author yanfengzhang
  14. * @date 2019-12-19 18:11
  15. */
  16. @SpringBootApplication
  17. @ComponentScan(basePackages = {"org.zyf.javabasic"})
  18. @EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
  19. @EnableSwagger2
  20. public class ZYFApplication {
  21. public static void main(String[] args) {
  22. ApplicationContext context = SpringApplication.run(ZYFApplication.class, args);
  23. }
 

其中对@SpringBootApplication进行展开分析:

 
  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by FernFlower decompiler)
  4. //
  5.  
  6. package org.springframework.boot.autoconfigure;
  7.  
  8. import java.lang.annotation.Documented;
  9. import java.lang.annotation.ElementType;
  10. import java.lang.annotation.Inherited;
  11. import java.lang.annotation.Retention;
  12. import java.lang.annotation.RetentionPolicy;
  13. import java.lang.annotation.Target;
  14. import org.springframework.boot.SpringBootConfiguration;
  15. import org.springframework.boot.context.TypeExcludeFilter;
  16. import org.springframework.context.annotation.ComponentScan;
  17. import org.springframework.context.annotation.FilterType;
  18. import org.springframework.context.annotation.ComponentScan.Filter;
  19. import org.springframework.core.annotation.AliasFor;
  20.  
  21. @Target({ElementType.TYPE})
  22. @Retention(RetentionPolicy.RUNTIME)
  23. @Documented
  24. @Inherited
  25. @SpringBootConfiguration
  26. @EnableAutoConfiguration
  27. @ComponentScan(
  28. excludeFilters = {@Filter(
  29. type = FilterType.CUSTOM,
  30. classes = {TypeExcludeFilter.class}
  31. ), @Filter(
  32. type = FilterType.CUSTOM,
  33. classes = {AutoConfigurationExcludeFilter.class}
  34. )}
  35. )
  36. public @interface SpringBootApplication {
  37. @AliasFor(
  38. annotation = EnableAutoConfiguration.class
  39. )
  40. Class<?>[] exclude() default {};
  41.  
  42. @AliasFor(
  43. annotation = EnableAutoConfiguration.class
  44. )
  45. String[] excludeName() default {};
  46.  
  47. @AliasFor(
  48. annotation = ComponentScan.class,
  49. attribute = "basePackages"
  50. )
  51. String[] scanBasePackages() default {};
  52.  
  53. @AliasFor(
  54. annotation = ComponentScan.class,
  55. attribute = "basePackageClasses"
  56. )
  57. Class<?>[] scanBasePackageClasses() default {};
  58. }
 

@SpringBootApplication包括三个注解,功能如下:

  • @SpringBootConfiguration(内部为@Configuration):被标注的类等于在spring的XML配置文件中(applicationContext.xml),装配所有bean事务,提供了一个spring的上下文环境
  • @ComponentScan:组件扫描,可自动发现和装配Bean(比如@Component和@Configuration),默认扫描SpringApplication的run方法里类所在的包路径下所有文件
  • @EnableAutoConfiguration:激活SpringBoot自动装配的特性

现在对主入口main方法进行展开来给出整体的流程图分析

二、SpringApplication构造过程分析

进入main里面的run方法,创建了一个SpringApplication实例,配置一些基本的环境变量、资源、构造器、监听器,进入这个SpringApplication有参构造函数

 
  1. public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
  2. this.sources = new LinkedHashSet();
  3. this.bannerMode = Mode.CONSOLE;
  4. this.logStartupInfo = true;
  5. this.addCommandLineProperties = true;
  6. this.addConversionService = true;
  7. this.headless = true;
  8. this.registerShutdownHook = true;
  9. this.additionalProfiles = new HashSet();
  10. this.isCustomEnvironment = false;
  11. this.resourceLoader = resourceLoader;
  12. Assert.notNull(primarySources, "PrimarySources must not be null");
  13. this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
  14. this.webApplicationType = WebApplicationType.deduceFromClasspath();
  15. this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
  16. this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
  17. this.mainApplicationClass = this.deduceMainApplicationClass();
  18. }
 

注意:在该构造方法内,做的工作就是把相关的类(主要是initializer和listener)加载进容器中,并没有执行

(一)验证主配置类不为空并且保存主类

(二)推断项目的类型

进入对应方法分析如下:

推断项目的类型可能为reactive、none、servlet三种类型,默认为servlet类型。其使用类加载器判断类型的逻辑如下

类型

判断情况

reactive

存在Spring WebFlux的DispatcherHandler存在,但是Spring MVC的DispatcherServlet不存在

none

二者都不存在

servlet

剩余所有情况

(三)初始化initializers

先进入ApplicationContextInitializer接口,这个接口只有一个方法initialize

 
  1. package org.springframework.context;
  2.  
  3. public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
  4. void initialize(C var1);
  5. }
 

查看实现了该这个接口的类进行分析

以SharedMetadataReaderFactoryContextInitializer实现类为例,跳转对应jar包,可以看到里面 spring.factories就在key为ApplicationContextInitializer中指定了对应的实现类,例如:

进入SharedMetadataReaderFactoryContextInitializer,其实现了ApplicationContextInitializer接口,并实现了里面的initialize方法

现在回到一开始再来看getSpringFactoriesInstance()方法,其核心为loadFactoryNames()方法

进入loadFactoryNames()方法,可以看到ApplicationContextInitializer的相关获取内容直接就是从文件“META-INF/spring.factories”中获取保存的

(四)加载相关的listeners

先进入ApplicationListener接口,这个接口只有一个方法onApplicationEvent

 
  1. package org.springframework.context;
  2.  
  3. import java.util.EventListener;
  4.  
  5. @FunctionalInterface
  6. public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
  7. void onApplicationEvent(E var1);
  8. }
 

查看实现了该这个接口的类进行分析

以BackgroundPreinitializer实现类为例,跳转对应jar包,可以看到里面 spring.factories就在key为ApplicationListener中指定了对应的实现类:

 进入BackgroundPreinitializer,其实现了ApplicationListener,并实现了里面的onApplicationEvent

方法如下:

现在回到一开始再来看getSpringFactoriesInstance()方法,其处理流程和上面的一样,即依然是从类路径下找到META-INF/spring.factories配置的所有ApplicationListener

(五)决定ApplicationClass主程序

进入deduceMainApplicationClass方法

三、SpringApplication启动过程分析

SpringBoot启动方案,包括启动流程的监听模块、加载配置环境模块、及核心的创建上下文环境模块以及后续的收尾回调等内容

(一)监控器监听容器启动并进行图形化页面处理

(二)监听器SpringApplicationRunListeners开启监听

直接开始分析ApringApplicationRunListeners,内含SpringApplicationRunListener的集合,其中starting方法就是对listeners进行遍历,对每个listener都调用starting方法

SpringApplicationRunListener和ApplicationListener都是SpringBoot中的事件监听器,但是它们所监听的事件和触发时机有所不同,其区别如下:

  1. 监听的事件不同
    SpringApplicationRunListener主要监听SpringApplication运行时的各种事件,例如应用程序开始启动、应用程序启动失败、应用程序启动完成等事件。而ApplicationListener主要监听Spring容器中的各种事件,例如Bean加载完成、上下文刷新完成等事件。
  2. 触发时机不同
    SpringApplicationRunListener在SpringApplication启动时就开始工作,可以接收到应用程序开始启动、应用程序启动失败、应用程序启动成功等各种事件。而ApplicationListener则是在Spring容器启动完成后,才能开始工作,监听的是Spring容器中的各种事件。
  3. 使用场景不同
    在实际应用中,SpringApplicationRunListener主要用于监听SpringApplication的启动过程,例如在应用程序启动前后执行某些操作、监听应用程序启动失败事件并做出相应的操作等。而ApplicationListener则用于监听Spring容器中的各种事件,例如在Bean加载完成后做出相应的操作、在上下文刷新完成后更新一些状态等。

总之,尽管SpringApplicationRunListener和ApplicationListener都是SpringBoot中的事件监听器,但是它们所监听的事件、触发时机、使用场景等都有所不同,我们需要根据具体的应用需求,选择合适的监听器来完成应用程序的事件处理。

在进入看一下SpringApplicationRunListener这个类

 
  1. package org.springframework.boot;
  2.  
  3. import org.springframework.context.ConfigurableApplicationContext;
  4. import org.springframework.core.env.ConfigurableEnvironment;
  5.  
  6. public interface SpringApplicationRunListener {
  7. void starting();
  8.  
  9. void environmentPrepared(ConfigurableEnvironment environment);
  10.  
  11. void contextPrepared(ConfigurableApplicationContext context);
  12.  
  13. void contextLoaded(ConfigurableApplicationContext context);
  14.  
  15. void started(ConfigurableApplicationContext context);
  16.  
  17. void running(ConfigurableApplicationContext context);
  18.  
  19. void failed(ConfigurableApplicationContext context, Throwable exception);
  20. }
 

对应方法说明如下

监听方法

运行阶段说明

SpringBoot起始版本

contextLoaded(ConfigurationApplicationEnvironment)

ConfigurableApplicationContext完成加载,但仍未启动;通知监听器,ApplicationContext已经完成IoC配置

1.0

contextPrepared(ConfigurationApplicationEnvironment)

ConfigurableApplicationContext准备妥当:通知监听器,ApplicationContext已经创建并初始化完成

1.0

environmentPrepared(ConfigurationEnvironment)

ConfigurationEnvironment准备妥当,允许将其调整

1.0

failed(ConfigurationApplicationEnvironment,Throwable)

Spring应用运行失败

2.0

running(ConfigurationApplicationEnvironment)

Spring应用正在运行

2.0

started(ConfigurationApplicationEnvironment)

ConfigurableApplicationContext已启动,此时SpringBean已初始化完成

2.0

starting()

run方法执行的时候立马执行:通知监听器,SpringBoot开始执行

1.0

总的来说就是创建了应用的监听器SpringApplicationRunListeners并调用start()开始监听,先在getRunListeners中获取了所有的监听器,然后starting开启

(三)environmentPrepared环境准备处理

分析这段代码,进入准备环境的方法prepareEnvironment中,可以看到如下:

首先创建了一个环境ConfigurationEnvironment(有的话就获取,没有则创建)

回到该方法返回的地方,通过this.configureEnvironment对环境进行设置,接着如下:

环境配置好以后回调了SpringApplicationRunListener的environmentPrepared函数,进入该方法:

可以看到environmentPrepared环境准备中进行了通知监听器,Environment准备完成。

回到开始处,可以看到环境准备完成后通过bindToSpringApplication将环境绑定到程序中。

(四)banner打印

打印对应的banner信息

也就是启动后的改部分,见如下

实际中,改图可以进行替换,只需要在resources增加banner.txt信息即可,例如如下:

其中的原理可以继续点开对应后续代码分析,这个后续中讲解替换思路。

(五)创建Spring应用上下文

创建应用上下文即IOC过程,IOC容器是驱动整体SpringBoot应用组件的核心,进入该方法:

这里的创建是根据SpringApplication在构造阶段所推断的web应用类型进行IOC容器的创建,IOC容器就是run返回的内容。

(六)Spring应用上下文准备阶段

prepareContext方法将listeners、environment、applicationArguments、banner等重要组件与上下文对象关联,对上下文对象进行进一步配置,进入该方法具体分析:

可以看到首先分别保存了刚才生成的environment、ApplicationContext,接下来的applyInitializers方法是执行初始化,进入该方法

方法内部遍历所有的initializer,然后依次回调里面所有的initialize方法(这些initializer就是在springboot刚启动时构造new springApplication时添加的),设置完当前环境并完成初始化之后,回调了所有Linsteners的contextPrepared方法

接下来将命令行参数和banner注册到IOC容器来,如下:

最后全部操作都完成后,这个方法回调了Listeners的contextLoaded方法,如上。

(七)Spring应用上下文刷新阶段

在该方法中首先注册了一个shutdownHook线程,用来实现SpringBean销毁生命周期回调

在执行完refresh之后的控制台,可以看到tomcat和一些IOC容器的bean都被加载进去了

 

(八)Spring应用上下文收尾阶段

其中afrerRefresh()并无内容处理,后续的版本中已经没有改方法了

 
  1. protected void afterRefresh(ConfigurableApplicationContext context,
  2. ApplicationArguments args) {
  3. }
 

收尾计时器停止,同时调用监听器的started()。

(九)回调工作处理

进入该方法分析

ApplicationContext就是IOC容器,这个方法从IOC容器中获取了所有的ApplicationRunner和ConmmandLineRunner,接下来进行遍历和回调。

在callRunners使用的这两个类几乎可以等价,都是用于做一些客户自定义的工作,而且是整个流程完成之后才会调用用户自己定义的实现类的run方法,这两个run方法的实现方法都是在容器基本初始化好的时候调用的。

紧接着,如果无异常代码执行如下:

监听器回调running()方法代表SpringApplication正常启动结束。

(十)SpringApplication启动异常处理

发生异常主要是对异常的处理,我们进入该方法分析

可以看到这个异常报告类也是支持自定义并且自动配置的,配置结束后,Springboot做了一些基本的收尾工作,返回了应用环境上下文(IOC容器)。

四、SpringBoot自动配置分析

Spring Boot 的自动化配置模块是该框架的核心功能之一,它可以大大简化应用程序的配置工作。下面是对 Spring Boot 自动化配置模块的讲解和分析:

  1. 自动化配置的原理:Spring Boot 的自动化配置模块基于约定优于配置的原则。它通过在 classpath 下扫描依赖和配置,自动配置应用程序的各个组件。它使用条件化配置的机制,根据环境和条件自动选择适当的配置。
  2. 自动配置的实现方式:Spring Boot 自动化配置模块使用了 @Conditional 注解和条件注解来实现条件化配置。这些注解可以根据一组条件来决定是否启用某个配置。例如,@ConditionalOnClass 根据 classpath 中是否存在指定的类来判断是否启用配置。
  3. 自动配置的加载顺序Spring Boot 的自动配置是通过在 classpath 下的 META-INF/spring.factories 文件中定义的自动配置类来实现的。这些自动配置类会被自动加载,并根据条件进行初始化和配置。根据条件的不同,可以有多个自动配置类被加载,它们会按照优先级顺序进行配置
  4. 自动配置的自定义:Spring Boot 允许开发者对自动配置进行自定义。你可以使用 @Conditional 注解和条件注解来定义自定义的条件,从而影响自动配置的行为。你还可以使用 @EnableAutoConfiguration 注解来控制自动配置的启用或禁用。
  5. 自动配置的好处:Spring Boot 的自动化配置模块带来了很多好处。它大大减少了手动配置的工作量,提高了开发效率。它提供了合理的默认配置,减少了错误配置的风险。同时,它的条件化配置机制使得应用程序更具灵活性,能够根据不同的环境和需求进行动态的配置。

总的来说,Spring Boot 的自动化配置模块是该框架的重要特性之一。它通过约定优于配置的原则和条件化配置机制,实现了自动加载和配置应用程序的各个组件。这为开发者提供了便利和灵活性,并大大简化了应用程序的配置过程。

现在回到我们一开始的图示分析,该配置模块的主要使用到了SpringFactoriesLoader,即Spring工厂加载器,该对象提供了loadFactoryNames方法,入参为factoryClass和classLoader,即需要传入工厂类名称和对应的类加载器,方法会根据指定的classLoader,加载该类加器搜索路径下的指定文件,即spring.factories文件,传入的工厂类为接口,获取到这些实现类的类名后,loadFactoryNames方法返回类名集合,方法调用方得到这些集合后,再通过反射获取这些类的类对象、构造方法,最终生成实例。

(一)自动装配原理分析

从@SpringBootApplication中的@EnableAutoConfiguration注解中可以看到其import了一个自动配置导入选择器AutoConfigurationImportSelect

 
  1. package org.springframework.boot.autoconfigure;
  2.  
  3. import java.lang.annotation.Documented;
  4. import java.lang.annotation.ElementType;
  5. import java.lang.annotation.Inherited;
  6. import java.lang.annotation.Retention;
  7. import java.lang.annotation.RetentionPolicy;
  8. import java.lang.annotation.Target;
  9. import org.springframework.context.annotation.Import;
  10.  
  11. @Target({ElementType.TYPE})
  12. @Retention(RetentionPolicy.RUNTIME)
  13. @Documented
  14. @Inherited
  15. @AutoConfigurationPackage
  16. @Import({AutoConfigurationImportSelector.class})
  17. public @interface EnableAutoConfiguration {
  18. String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
  19.  
  20. Class<?>[] exclude() default {};
  21.  
  22. String[] excludeName() default {};
  23. }
 

其类图如下

可以发现其最终实现了ImportSelector(选择器)和BeanClassLoaderAware(bean类加载器中间件),其中这个选择器的作用就是导入组件。

所有自动装配的逻辑都是在AutoConfigurationImportSelector里面的selectImports方法中实现的

进入getAutoConfigurationEntry()方法

进入getCandidateConfigurations()获取候选配置方法,可以看到核心的SpringFactoriesLoader的loadFactoryNames()方法

其中SpringFactoriesLoader是Spring Framework工厂机制的加载器,loadFactoryNames是其对应的加载方法,进入这个核心的loadFactoryNames方法中查看

该处加载原理如下:

  • 扫描所有jar包路径下 META-INF/spring.factories,这里是通过类加载器生成对应的url路径
  • 把扫描到的内容包装成properties对象,并对这个对象的内容进行遍历,返回map,map的key为接口的全类名,value为接口全部实现类列表(列表里元素去重,防止重复加载),这个value的信息后续会作为loadSpringFactories方法的返回值
  • 在上一步返回的map之中查找并返回指定类名映射的实现类全类名列表

再看刚才getCandidateConfiguration方法中的getSpringFactoriesLoaderFactoryClass方法,返回的就是EnableAutoConfiguration类

也就是说要从刚才properties中再获取这个类对应的值,把它们加到容器中。

选取mybatis-spring-boot-autoconfigure下的spring.factories文件分析一下:

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

只有进入到容器中,这些自动配置类才会起作用——进行自动配置功能

(二)条件化自动装配

对于使用@Configuration的自动配置类,其条件自动化装配以@condition为核心。在spring底层中的@conditional注解会根据不同的满足条件生效整个配置类里面的配置。

条件化装配可以分为以下几类:

Class条件注解

注解

说明

@ConditionalOnClass

指定类存在时生效

@ConditionalOnMissingClass

指定类缺失时生效

Bean条件注解

注解

说明

@ConditionalOnBean

指定Bean存在时生效

@ConditionalOnMissingBean

指定Bean缺失时生效

属性条件注解

注解

说明

@ConditionalOnProperty

使用属性(application.properties)的值判断是否生效

Web应用条件注解

注解

说明

@ConditionalOnWebApplication

是web类型时生效

@ConditionalOnNotWebApplication

不是web类型时生效

其他条件注解

@Conditional扩展注解

作用(判断是否满足当前指定条件)

@ConditionalOnJava

系统的java版本是否符合要求

@ConditionalOnExpression

满足SpEL表达式指定

@ConditionalOnSingleCandidate

容器中只有一个指定的Bean,或者这个Bean是首选Bean

@ConditionalOnResource

类路径下是否存在指定资源文件

@ConditionalOnJndi

JNDI存在指定项

分析@ConditionalOnWebApplication

 
  1. package org.springframework.boot.autoconfigure.condition;
  2.  
  3. import java.lang.annotation.Documented;
  4. import java.lang.annotation.ElementType;
  5. import java.lang.annotation.Retention;
  6. import java.lang.annotation.RetentionPolicy;
  7. import java.lang.annotation.Target;
  8. import org.springframework.context.annotation.Conditional;
  9.  
  10. @Target({ElementType.TYPE, ElementType.METHOD})
  11. @Retention(RetentionPolicy.RUNTIME)
  12. @Documented
  13. @Conditional({OnWebApplicationCondition.class})
  14. public @interface ConditionalOnWebApplication {
  15. ConditionalOnWebApplication.Type type() default ConditionalOnWebApplication.Type.ANY;
  16.  
  17. public static enum Type {
  18. ANY,
  19. SERVLET,
  20. REACTIVE;
  21.  
  22. private Type() {
  23. }
  24. }
  25. }
 

进入OnWebApplicationCondition类,里面有一个getMatchOutcome()方法,就是判断是否符合当前配置条件

该方法首先判断是否使用了这个注释,然后使用isWebApplication来判断当前是否是web应用,这些match的方法判断指定的条件成立,才会给容器添加组件,配置内容才会生效。

(三)自动配置原理举例:HttpEncodingAutoConfiguration(HTTP编码自动配置)

可以看到以下信息:

  • @Configuration 代表这是一个配置类,类似编写的配置文件,也可以给容器中添加组件。
  • @EnableConfigurationProperties 启用指定类的ConfigurationProperties功能,将配置文件application.properties的值和ServerProperties绑定起来,并把ServerProperties加入到IOC容器中。
  • @ConditionalOnClass用来判断当前项目是否含有这个类,这里CharacterEncodingFilter的作用就是springMVC乱码解决的过滤器(以前在spring的xml文件中配置的),如果有这个过滤器则配置生效。
  • @ConditionalOnProperty判断这个配置是否存在,matchIfMissing = true代表即使配置文件中不存在这个属性也是默认生效的。

需要注意的是,在spring.factories中的自动配置类不是都能生效的,都有各自的生效条件。根据当前不同条件判断,来决定这个配置类是否生效;一旦配置类生效,这个配置类就会给容器添加各种组件,这些组件的属性从对应的properties中获取,这些类里面的每一个属性又是和配置文件绑定的。

五、总结

Spring Boot 的自动化配置和启动流程为开发者提供了简化的开发体验,降低了配置和启动的复杂性。通过深入理解 SpringApplication 的启动步骤、自动配置的原理以及 Spring Boot 如何无缝集成各类组件,我们不仅能更好地运用 Spring Boot,还能更灵活地定制和优化应用。自动配置是 Spring Boot 的核心之一,它通过精巧的条件判断实现了“按需配置”,确保应用在减少冗余的前提下获得所需的功能支持。

在实际开发中,理解这些原理可以帮助我们在遇到问题时更快找到原因,尤其是当我们需要进行调优或者定制配置时,更能从容应对。希望通过本文的分析,你能够更全面地掌握 Spring Boot 的核心机制,并在实际项目中充分发挥它的优势。

posted @ 2025-05-12 17:57  CharyGao  阅读(316)  评论(0)    收藏  举报