Spring Boot自动装配原理解析

Spring Boot 自动装配,是 Spring Boot 的核心特性之一。下面我来详细介绍一下Spring Boot 实现自动装配的原理。

一、什么是自动装配?

自动装配是 Spring Boot 基于约定大于配置的原则,根据项目的依赖和配置,自动配置 Spring 应用程序所需 Bean 的过程。

二、核心注解 @SpringBootApplication

java 复制代码
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

@SpringBootApplication 是一个复合注解,包含三个核心注解:

1. @SpringBootConfiguration

java 复制代码
@Configuration
public @interface SpringBootConfiguration {
    // 继承 @Configuration,标识为配置类
}

2. @ComponentScan

java 复制代码
@ComponentScan
// 自动扫描当前包及其子包的组件

3. @EnableAutoConfiguration最关键

java 复制代码
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    // 启用自动配置
}

三、自动装配执行流程

核心类:AutoConfigurationImportSelector

java 复制代码
public class AutoConfigurationImportSelector implements ... {
    
    @Override
    public String[] selectImports(AnnotationMetadata metadata) {
        // 1. 判断是否开启自动装配
        if (!isEnabled(metadata)) {
            return NO_IMPORTS;
        }
        
        // 2. 获取所有自动配置类
        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(metadata);
        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
    }
    
    protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata metadata) {
        // 3. 获取所有候选配置类
        List<String> configurations = getCandidateConfigurations(metadata, attributes);
        
        // 4. 去重
        configurations = removeDuplicates(configurations);
        
        // 5. 根据 @Conditional 注解排除不需要的配置
        Set<String> exclusions = getExclusions(metadata, attributes);
        configurations.removeAll(exclusions);
        
        // 6. 过滤(关键步骤)
        configurations = getConfigurationClassFilter().filter(configurations);
        
        // 7. 触发自动配置导入事件
        fireAutoConfigurationImportEvents(configurations, exclusions);
        
        return new AutoConfigurationEntry(configurations, exclusions);
    }
}

四、配置加载机制

1. spring.factories 文件

Spring Boot 在 META-INF/spring.factories 中定义自动配置类:

java 复制代码
properties

# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
  org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
  org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
  ...

2. Spring Boot 2.7+ 的变化

Spring Boot 2.7 开始,推荐使用新的方式

  • META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
bash 复制代码
properties

# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration

五、条件注解(Conditional)

自动装配的核心是 条件化配置

注解 作用
@ConditionalOnClass 类路径下存在指定类时生效
@ConditionalOnMissingClass 类路径下不存在指定类时生效
@ConditionalOnBean 容器中存在指定 Bean 时生效
@ConditionalOnMissingBean 容器中不存在指定 Bean 时生效
@ConditionalOnProperty 配置属性满足条件时生效
@ConditionalOnWebApplication 是 Web 应用时生效
@ConditionalOnExpression SpEL 表达式为 true 时生效

示例:DataSourceAutoConfiguration

java 复制代码
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class, 
         DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {
    
    @Configuration
    @Conditional(EmbeddedDatabaseCondition.class)
    @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
    @Import(EmbeddedDataSourceConfiguration.class)
    protected static class EmbeddedDatabaseConfiguration {
    }
    
    @Configuration
    @Conditional(PooledDataSourceCondition.class)
    @ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
    @Import({ DataSourceConfiguration.Hikari.class,
              DataSourceConfiguration.Tomcat.class,
              DataSourceConfiguration.Dbcp2.class,
              DataSourceConfiguration.Generic.class })
    protected static class PooledDataSourceConfiguration {
    }
}

六、自动装配执行顺序

java 复制代码
启动类 → @SpringBootApplication → @EnableAutoConfiguration
     ↓
AutoConfigurationImportSelector.selectImports()
     ↓
加载 spring.factories / AutoConfiguration.imports
     ↓
过滤(按条件注解排除)
     ↓
按 @AutoConfigureOrder, @AutoConfigureAfter, @AutoConfigureBefore 排序
     ↓
注册配置类到容器
     ↓
配置类中的 @Bean 方法创建 Bean

七、自定义 Starter 实现自动装配

1. 创建自动配置类

java 复制代码
@Configuration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MyAutoConfiguration {
    
    @Bean
    @ConditionalOnMissingBean
    public MyService myService(MyProperties properties) {
        return new MyService(properties);
    }
}

2. 创建配置属性类

java 复制代码
@ConfigurationProperties("my.service")
public class MyProperties {
    private String prefix = "default";
    private boolean enabled = true;
    // getters/setters
}

3. 注册配置

META-INF/spring/ 目录创建文件:

java 复制代码
properties

# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.MyAutoConfiguration

4. spring.factories(兼容旧版本)

java 复制代码
properties

# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.example.MyAutoConfiguration

八、调试和排除

1. 查看生效的自动配置

java 复制代码
yaml

# application.yml
debug: true

启动时会输出:

java 复制代码
Positive matches:    # 已启用的自动配置
Negative matches:    # 未启用的自动配置
Exclusions:          # 排除的配置
Unconditional classes: # 无条件配置

2. 排除特定自动配置

java 复制代码
@SpringBootApplication(exclude = {
    DataSourceAutoConfiguration.class,
    JacksonAutoConfiguration.class
})

或配置文件:

java 复制代码
yaml

spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

九、核心原理总结

  1. 启动入口@SpringBootApplication@EnableAutoConfiguration

  2. 配置加载 :通过 spring.factoriesAutoConfiguration.imports 加载配置类

  3. 条件过滤 :使用 @Conditional 系列注解按条件启用/禁用配置

  4. Bean 注册 :符合条件的配置类中的 @Bean 方法向容器注册 Bean

  5. 属性绑定 :通过 @ConfigurationProperties 绑定外部配置

十、最佳实践

  1. 合理使用条件注解,确保配置只在需要的场景生效

  2. 明确配置顺序 ,使用 @AutoConfigureBefore/@AutoConfigureAfter

  3. 提供合理的默认值,同时允许用户覆盖

  4. spring-autoconfigure-metadata.properties 中预定义条件,加快启动速度

  5. 模块化配置,将相关功能放在同一个自动配置类中

自动装配是 Spring Boot"约定大于配置"理念的具体实现,大大简化了 Spring 应用的配置工作。

相关推荐
程序员小假2 小时前
我们来说一下 synchronized 与 ReentrantLock 的区别
java·后端
益达3212 小时前
【避坑指南】Maven依赖冲突怎么解决?用mvn dependency:tree一眼看清
java
码事漫谈2 小时前
C++多线程中join与detach机制深度解析
后端
驱动探索者2 小时前
[缩略语大全]之[内存管理]篇
java·网络·算法·内存管理
okseekw3 小时前
Java反射:解锁框架开发的终极密码,让代码拥有"动态灵魂"!
java·后端
码农水水3 小时前
腾讯Java面试被问:阻塞队列BlockingQueue的实现原理
java·后端·python·面试
京东零售技术3 小时前
15 年评价中台如何涅槃?超百亿数据×千万 QPM×百万行代码的重构全景复盘
后端
廋到被风吹走3 小时前
【Spring】BeanPostProcessor详解
java·后端·spring
bbq粉刷匠3 小时前
二叉树中两个指定节点的最近公共祖先
java·算法