当前位置: 首页 > news >正文

Springboot的自动配置究竟如何生效?

从@import讲起

学 Spring Boot 的时候,我一直在想一个问题:明明就加了一个 `spring-boot-starter-web` 的依赖,Tomcat 自己就跑起来了,JSON 解析器也自动好了,我啥也没写。这不科学吧?Java 又不是魔法。直到我扒开 @SpringBootApplication 看了一眼,才发现真相就藏在一行注解里。

拆开 @SpringBootApplication

你要是用 IDE 点进去看,会发现它其实是个套娃:

```java

@SpringBootConfiguration

@EnableAutoConfiguration ← 这个是关键

@ComponentScan

```

@ComponentScan 好理解——扫包。

@SpringBootConfiguration 就是个 @Configuration 的别名。

唯独 @EnableAutoConfiguration 这个名字起得玄乎。"自动配置"四个字听着就让人犯怵,好像 Spring 替你干了多少了不起的事似的。

再点进去:

```java

@Import(AutoConfigurationImportSelector.class)

public @interface EnableAutoConfiguration { ... }

```

好家伙,又是个 @Import。到这一步就清晰了——所谓"自动配置",本质上就是把一个类 Import 进来干活。

## @Import 到底是什么

很多人把 @Import 当成一个冷门注解,平时用不上。其实它是 Spring 最核心的机制之一。

@Import 做的事很简单:**手动把一个类塞进 IoC 容器**。类似于 @Bean,只不过 @Bean 写在方法上,@Import 写在类上。

Spring 框架里有三种用法:

- **普通类**:`@Import(MyClass.class)` → 直接注册

- **Configuration 类**:`@Import(MyConfig.class)` → 连配置类里的 @Bean 一起注册

- **ImportSelector**:这个最狠——它让你可以动态决定要注册哪些类

自动配置就是第三种。

## AutoConfigurationImportSelector 在干什么

这个 Selector 的套路其实不复杂:

1. 读取 `META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports` 文件

2. 把里面写的所有类全限定名读出来

3. 用条件注解过滤一遍,把不满足条件的扔掉

4. 剩下的全部注册进容器

说白了,Spring Boot 启动的时候就是去读了一个文件,文件里列了一堆配置类的名字,然后挨个加载。

所以自动配置本身没有任何黑科技。你要是愿意,自己也能写一个 xxx.imports 文件,塞进自己的 jar 包,Spring Boot 启动时就会帮你自动加载。

## 条件注解——为什么加个依赖就生效

现在的问题变成了:既然 AutoConfiguration.imports 里写了那么多配置类,那岂不是不管我用不用,它都会加载?

答案是:**都加载了,但不一定生效。**

每个配置类上面都有一堆条件:

```java

@ConditionalOnClass(RedisOperations.class)

@ConditionalOnMissingBean(RedisTemplate.class)

public class RedisAutoConfiguration { ... }

```

翻译成人话:**"项目里要有 Redis 的依赖,同时用户没自己定义 RedisTemplate,我的配置才生效。"**

这就是为什么你加个 `spring-boot-starter-data-redis`,RedisTemplate 就自动能用了。不是 Spring 猜到了你的心思,而是它加载了 RedisAutoConfiguration,检查类路径下确实有 Redis 的 jar,用户也没自己搞,那就帮你 new 一个。

反过来,你只要自己写了一个 `@Bean RedisTemplate`,Spring 看到 `@ConditionalOnMissingBean`,二话不说就闭嘴了——用户最大。

## 用 OSS Starter 串一遍

这个抽象的概念,我拿自己的阿里云 OSS starter 来串一遍,你就全明白了。

首先我的 autoconfigure 模块里有这几个东西:

**AliyunOSSProperties.java**——负责从 yml 读配置:

```java

@ConfigurationProperties(prefix = "aliyun.oss")

public class AliyunOSSProperties {

private String endpoint;

private String bucketName;

private String region;

// getter/setter

}

```

**AliOssUtil.java**——真正干活的工具类,不戴任何注解:

```java

public class AliOssUtil {

private final AliyunOSSProperties properties;

private OSS ossClient;

public AliOssUtil(AliyunOSSProperties properties) {

this.properties = properties;

}

@PostConstruct

public void init() {

// 用 properties 的值初始化 OSSClient

}

public String upload(MultipartFile file) {

// 上传逻辑

}

}

```

**AliyunOssConfiguration.java**——真正的配置类,负责串联:

```java

@Import(AliyunOSSProperties.class)

@Configuration

public class AliyunOssConfiguration {

@Bean

public AliOssUtil aliOssUtil(AliyunOSSProperties properties) {

return new AliOssUtil(properties);

}

}

```

**AutoConfiguration.imports**——注册文件:

```

com.aliyun.oss.AliyunOssConfiguration

```

启动的时候流程是这样的:

Spring 扫到我的 jar 里的 AutoConfiguration.imports → 看到 AliyunOssConfiguration → 走到 @Import 把 AliyunOSSProperties 塞进容器 → 触发 @ConfigurationProperties 去读 yml 里的 aliyun.oss.* → 把读到的值填进 Properties → 执行 @Bean aliOssUtil,把填好值的 Properties 传进去 → AliOssUtil 拿着配置信息初始化 OSS 客户端。

用户那边只要做两件事:

1. 引入 starter 依赖

2. yml 里写几行配置

然后直接在 Controller 里 @Autowired 就拿到了一个已经配置好的 AliOssUtil。

## 一句话总结

自动配置不是什么魔法。就是 Spring Boot 启动时读了一个文件,按文件里的名单加载配置类,再根据条件注解决定哪些配置实际生效。

整个链路就四个环节:

```

AutoConfiguration.imports → 配置类 → @Import → @Bean

```

搞懂这个,你就弄清楚了 Spring Boot 最引以为傲的"自动配置"到底是个啥。下次面试官问到这个,你就从 @Import 讲起——比你背一百遍"自动配置是 Spring Boot 的一大特性"管用得多。

http://www.jsqmd.com/news/773857/

相关文章:

  • 收藏!小白也能入局:月薪60k AI大模型应用开发工程师,是你转行的绝佳机会?
  • 跨部门协作:如何让“水火不容“的开发与运维团队“并肩作战“?
  • OpenClaw Battle Arena:基于主机-控制器分离架构的AI格斗竞技场开发指南
  • 2026毕业季实测:这几款论文降AI工具,一键清零AIGC痕迹
  • TinyML与边缘计算:MCU上的机器学习部署实践
  • FastAPI SDK:企业级Web服务开发的模块化脚手架与最佳实践
  • Windows安卓应用安装神器:APK-Installer完全指南
  • 2026年05月07日最热门的开源项目(Github)
  • 2025届毕业生推荐的五大AI辅助论文工具推荐榜单
  • YOLO系列语义分割下采样改进:全网首发--使用 FSConv 改进 频域分离下采样卷积 ✨
  • 基于eBPF的零插桩AI智能体观测:AgentSight内核级监控实战
  • 全地形车多维度动态稳定协同姿态串联式主动悬架【附代码】
  • DeepSeek-450亿美元估值-国家大基金入局
  • 微信机器人开发实战:从协议模拟到插件化架构
  • 现代前端模式库实践:从原子设计到工程化落地
  • Godot引擎写实水体Shader实现:从原理到优化的完整指南
  • 【C++模板】:开启泛型编程之门(函数模版,类模板)
  • 告别碎片化焦虑:KNOTA 诺达如何用“AI + 双链”打造你的智能第二大脑?
  • 3步掌握GetQzonehistory:永久备份QQ空间所有回忆的终极指南
  • 基于双向比的高速工程车辆互连式半主动油气悬架多级阻尼切换【附代码】
  • 技术重构:魔兽地图数据格式转换的范式迁移
  • VideoDownloadHelper实战解密:突破视频下载限制的终极工具
  • AI编码代理安全防护:Rampart防火墙部署与策略配置实战
  • AISMM评估结果不准?SITS2026案例暴露出的7类典型误判及校准方法论,立即自查
  • LORE:为AI编码助手注入架构记忆,提升大型TypeScript项目可维护性
  • AI 算力新格局:端侧突围与算力基建“三级跳”,OpenAI 酝酿已久的智能手机自研计划开始实施
  • 性价比高的 GEO优化靠谱企业
  • 避坑指南!IDEA + WSL 2 + Java 8 环境配置的四大终极深坑
  • Java开发者收藏:AI大模型转型学习路线与实战指南
  • 从Cal.com到coss.com:现代前端架构实战与开源基础设施堆栈解析