学会SpringBoot启动原理,轻松掌握Spring Boot自动化配置

文摘   2024-12-14 23:40   江苏  

Spring Boot 是 Java 开发的“神器”,它以简单、快速、优雅著称,但你有没有想过它是如何实现“开箱即用”的?为什么我们只需要一个@SpringBootApplication 就能启动完整的应用?本篇文章,我们将深入 Spring Boot 的启动原理,帮助你轻松掌握自动化配置的核心机制。

Spring Boot 的大门

@SpringBootApplication 是 Spring Boot 的“总控注解”,它是整个 Spring Boot 应用的入口。这个注解看似简单,实际上是一个组合注解,包含了多个功能强大的注解。

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@SpringBootConfiguration@EnableAutoConfiguration@ComponentScan(excludeFilters = {     @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),    @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })public @interface SpringBootApplication {}

我们来拆解一下这个注解:

  • @SpringBootConfiguration:其实就是@Configuration,标记这是一个配置类,用于定义 Spring 的 Bean。
  • @EnableAutoConfiguration:顾名思义,开启自动化配置。这个是今天的重点,我们稍后深入分析。
  • @ComponentScan:负责扫描指定包下的组件(比如@Service@Controller),自动注册到 Spring 容器中。

温馨提示
@SpringBootApplication 默认会扫描当前类所在包及其子包的所有组件。因此,启动类通常放在项目的根包下。若组件不在默认扫描路径下,可以通过@ComponentScan 手动指定路径。


自动配置的核心

@EnableAutoConfiguration 是 Spring Boot 自动化配置的“总开关”。它的实现逻辑隐藏在两个关键点中:

  1. @AutoConfigurationPackage:自动扫描第三方库的组件。
  2. @Import(AutoConfigurationImportSelector.class):导入自动配置类的选择器。

简单来说,@EnableAutoConfiguration 会加载 Spring Boot 提供的所有自动化配置类,然后根据项目中实际引入的依赖和条件,决定哪些配置生效。


自动化配置的幕后英雄

AutoConfigurationImportSelector 是 Spring Boot 自动化配置的“大脑”。它会筛选出所有符合条件的自动化配置类并加载。我们来看核心方法:

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineprotected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {    if (!isEnabled(annotationMetadata)) {        return EMPTY_ENTRY;    }    AnnotationAttributes attributes = getAttributes(annotationMetadata);    List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);    configurations = removeDuplicates(configurations);    Set<String> exclusions = getExclusions(annotationMetadata, attributes);    checkExcludedClasses(configurations, exclusions);    configurations.removeAll(exclusions);    configurations = getConfigurationClassFilter().filter(configurations);    fireAutoConfigurationImportEvents(configurations, exclusions);    return new AutoConfigurationEntry(configurations, exclusions);}

这个方法的工作流程可以总结为以下几步:

1. 检查自动化配置是否开启

通过spring.boot.enableautoconfiguration 属性可以全局控制自动化配置的开关:

ounter(lineounter(lineounter(lineprotected boolean isEnabled(AnnotationMetadata metadata) {    return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);}

示例
application.properties 中关闭自动化配置:

ounter(linespring.boot.enableautoconfiguration=false

2. 获取候选配置类

候选配置类主要来自两个地方:

  • META-INF/spring.factories 文件:定义了大量的自动化配置类。
  • META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件:Spring Boot 3.x 版本新增,存储配置类的路径更规范。
ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineprotected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {    List<String> configurations = new ArrayList<>(        SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader())    );    ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);    return configurations;}

温馨提示
spring.factories 是 Spring Boot 自动化配置的核心文件,里面记录了所有 Starter 的自动化配置类路径。


条件注解:让配置更智能

Spring Boot 的自动化配置并不是“无脑”加载,而是通过一系列条件注解 来决定配置是否生效。

常见条件注解

  • @ConditionalOnClass:当类路径下存在某个类时生效。例如 Redis 的自动配置类:
ounter(lineounter(lineounter(lineounter(lineounter(line@Configuration@ConditionalOnClass(name = "org.springframework.data.redis.core.RedisTemplate")public class RedisAutoConfiguration {    // Redis 的相关配置}

如果项目中没有引入 Redis 相关依赖,这个配置类就不会生效。

  • @ConditionalOnBean:当 Spring 容器中存在某个 Bean 时生效。
  • @ConditionalOnProperty:当配置文件中存在指定属性时生效。

示例
自定义一个条件注解的使用:

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line@Configuration@ConditionalOnProperty(prefix = "my.feature", name = "enabled", havingValue = "true")public class MyFeatureConfiguration {
    @Bean    public String myFeatureBean() {        return "My Feature is Enabled!";    }}

application.properties 中启用该配置:

ounter(linemy.feature.enabled=true

enabled 设置为true 时,myFeatureBean 才会被注册到 Spring 容器中。


自动化配置的排除机制

有时候,我们可能不想使用某些自动化配置。这时可以通过以下方式排除它们:

1. 注解排除

直接在启动类上通过exclude 属性排除配置类:

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(line@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})public class MyApplication {    public static void main(String[] args) {        SpringApplication.run(MyApplication.class, args);    }}

2. 配置文件排除

通过spring.autoconfigure.exclude 属性在配置文件中排除:

ounter(linespring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

温馨提示
排除配置类时要确保类的全路径正确,否则会导致项目启动失败。


总结

Spring Boot 的启动原理看似复杂,但核心逻辑可以归纳为以下几点:

  1. @SpringBootApplication 是组合注解,整合了配置、扫描和自动化配置功能。
  2. @EnableAutoConfiguration 是自动化配置的核心,通过加载spring.factories 中定义的配置类实现。
  3. 自动化配置类通过条件注解 判断是否生效,确保只加载必要的配置。
  4. 我们可以通过注解或配置文件排除不需要的自动化配置。

Spring Boot 的魔力源于它的“约定优于配置”和“条件加载”机制。理解了这些原理,再复杂的 Spring Boot 应用你也能轻松驾驭!

夜半探案
每日一案,一案一法,一起学习生活中的法律知识。
 最新文章