本篇文章讲述 Spring Boot 自动装配的概念和实战, 开发一个 starter, 穿插自动装配的知识点理解。
什么是自动装配?
在传统 Spring 里,我们需要在 applicationContext.xml
或者配置类里,手动写 一堆 <bean>
或 @Bean
,告诉 Spring 要创建哪些对象(Bean)。
Spring Boot 的目标是"约定大于配置",让开发者尽量少写配置,所以它引入了 自动装配,
定义: 自动装配 = Spring Boot 根据当前 classpath 里的依赖、配置文件和条件判断,自动帮你注册合适的 Bean 到容器中。
你只要引了依赖,Spring Boot 就猜到你要用啥,并帮你准备好对应的 Bean。
接下来实战上手自动装配,再深入讲原理。
需求分析
开发一个 excel 文档导出,要求在查询接口上使用注解,便捷导出 excel 文档。
方案
我们开发一个starter , starter 用到了自动装配功能 , 而且 starter 已经做了相关的配置和需要的依赖,调用方引入我们的stater, 通过一个注解就能实现 excel 文档导出,符合需求中要的便捷性。
环境说明
- spring boot 3.5.6
- java 21
- Spring web
- lombok
- 第三方依赖 Apache POI (操作 Excel)
pom 依赖:
注意打 jar 包的插件,不能打成可执行 jar,而是普通 jar 包,否则其它模块无法引用 jar 包。
xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.demoexcel</groupId>
<artifactId>excel-stater</artifactId>
<version>1.0.0</version>
<name>ExcelExportAutoConfig</name>
<description>ExcelExportAutoConfig</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>21</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Spring Boot Web MVC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.36</version>
<optional>true</optional>
</dependency>
<!-- Spring Boot AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--Apache POI 来操作 Excel-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip> <!-- 不生成可执行 jar -->
</configuration>
</plugin>
</plugins>
</build>
</project>
SpringBoot 实现 excel 导出功能
我们先开发导出功能,再加入自动装配,然后可以生成一个starter 最终让别的项目引入,便可以从实践得出 spring boot 自动装配与 starter 的效果。
项目名称:my-excel-starter
初始化后端项目,依赖安装环境说明配置。
application.yml 配置文件啥也不用写,追求快速上手。
开发流程:
- 编写一个注解 @ExcelExport
- 编写一个 AOP 切面, 切面内先让切入点执行方式,得到方法的返回值,使用 Apache POI 操作 excel 导出。
- controller 开发一个 exportUser 接口(理解成一个list查询接口),接口内模拟两条查询到的假数据。使用 @ExcelExport 便能实现导出功能。
功能开发好了我们再加入自动装配。
- 注解开发
java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcelExport {
String filename() default "export.xlsx";
}
- 切面开发
java
/**
* AOP , 导出Excel 文件
*/
@Aspect
@Component
public class ExcelExportAspect {
@SneakyThrows
@Around("@annotation(excelExport)")
public Object exportExcel(ProceedingJoinPoint pjp, ExcelExport excelExport) {
Object result = pjp.proceed();
if (result instanceof List<?> list && !list.isEmpty() && list.get(0) instanceof Map<?,?> row) {
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder
.currentRequestAttributes())
.getResponse();
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("Sheet1");
// 表头
Row header = sheet.createRow(0);
int col = 0;
for (Object key : row.keySet()) {
header.createCell(col++).setCellValue(key.toString());
}
// 数据
int rowNum = 1;
for (Object obj : list) {
Map<?, ?> map = (Map<?, ?>) obj;
Row dataRow = sheet.createRow(rowNum++);
int c = 0;
for (Object value : map.values()) {
dataRow.createCell(c++).setCellValue(value != null ? value.toString() : "");
}
}
// 写入 HttpServletResponse
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition",
"attachment; filename=" + URLEncoder.encode(excelExport.filename(), "UTF-8"));
workbook.write(response.getOutputStream());
workbook.close();
return null;
}
return result;
}
}
- controller 接口测试导出功能
java
@RestController
public class DemoController {
@ExcelExport(filename = "users.xlsx")
@GetMapping("/export")
public List<Map<String, Object>> exportUsers() {
List<Map<String, Object>> list = new ArrayList<>();
list.add(Map.of("id", 1, "name", "Alice", "age", 20));
list.add(Map.of("id", 2, "name", "Bob", "age", 25));
return list;
}
}
测试,访问 localhost:8080\export 自动下载 excel 文件。
功能开发完成,我们把这个项目当成一个工具,提供给别的项目使用,为了便于其它项目使用,实现自动装配。
自动装配
工作原理
名词解释:
@Bean (标记方法): 声明一个工厂方法,返回值对象会注册到 Spring 容器,成为一个 Bean。
@Configuration : 声明这是一个配置类,里面的 @Bean
方法会被 Spring 识别,用来定义 Bean。
@Configuration
本身也是@Component
,会被 Spring 扫描并注册为 Bean。- Spring 会用 CGLIB 代理增强这个类。
- 调用
@Bean
方法时,会拦截调用,确保返回的是容器里已有的单例,而不是新对象。
@Component : 如果与 @Bean 搭配 , Spring 不会用代理,每次调用Bean的方法都是 new 一个新的对象。
如何实现自动装配?
Spring Boot 的自动装配流程大概是这样:
当你启动一个 Spring Boot 应用时(@SpringBootApplication
)。
- @SpringBootApplication 注解内部有
**@EnableAutoConfiguration**
。 - 加载自动配置类
-
@EnableAutoConfiguration
→@Import(AutoConfigurationImportSelector.class)
。 -
AutoConfigurationImportSelector
会去扫描配置文件: -
Spring Boot 2.x →
META-INF/spring.factories
-
Spring Boot 3.x →
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
-
找到所有的
xxxAutoConfiguration
类(比如DataSourceAutoConfiguration
、WebMvcAutoConfiguration
)。
- 注册配置类
- 这些自动配置类(其实就是
@Configuration
类)被 注册到 Spring 容器,但还没有立即实例化 Bean。
- 条件判断(筛选)
-
每个自动配置类、或者其中的 Bean 方法,通常带有
@Conditional
系列注解: -
@ConditionalOnClass
:classpath 里有某个类才生效 -
@ConditionalOnMissingBean
:用户没有自定义 Bean 才生效 -
@ConditionalOnProperty
:配置文件里设置了某个属性才生效 -
Spring 会根据这些条件,决定哪些配置类/Bean 要真正装配。
- 注册 Bean 定义
- BeanDefinitionRegistry (Bean的总入口) 负责把各种来源的 **Bean 定义信息转成 BeanDefinition ,**最后存到一个映射表里(
BeanDefinitionMap
)。 - BeanFactory 负责根据 BeanDefinition 实例化对象。
- 容器刷新(refresh) → 实例化 Bean
- Spring 容器开始创建单例 Bean,执行依赖注入。
- 这时,自动配置的 Bean 就和你手动写的 Bean 一起被实例化,进入 Spring 上下文。
可以看出自动配置很灵活,按条件注册Bean 。
注意:spring 3.x 使用 META-INF\spring\org.springframework.boot.autoconfigure.AutoConfiguration.imports
作为自动装配的配置文件,区别于 spring 2.x 使用的 META-INF/spring.factories
以上可知,想要实现自动装配核心要编写:
- 编写自动配置类 xxxxAutoConfiguration
- 配置文件
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
开发实现
- 编写自动配置类 ExcelExportAutoConfiguration , 打上条件注解@ConditionalOnMissingBean(ExcelExportAspect.class) , 如果不存在ExcelExportAspect.class 才会加载这个配置类。
java
@Configuration
@ConditionalOnMissingBean(ExcelExportAspect.class)
public class ExcelExportAutoConfiguration {
@Bean
public ExcelEx
portAspect excelExportAspect() {
return new ExcelExportAspect();
}
}
- AutoConfiguration.imports 放入你想要自动装配的配置类
java
com.demoexcel.excelstater.config.ExcelExportAutoConfiguration
目录结构如下

生成 stater
经过以上步骤,已经开发好了一个 stater, 接下来仅需 maven install 打出一个 jar 包,在其它项目使用测试效果。

双击以后,本地maven仓库会有一个依赖包,可在其它项目中引入,依赖包的坐标是本项目的坐标:

确认本地maven仓库有这个依赖:C:\Users\Administrator.m2\repository\com\demoexcel

引入 starter
刚刚生成了一个 starter 我们自己测试看效果。
-
创建一个Spring boot项目,项目名称: example-excel,基本 web 依赖。
-
引入 starter,新项目直接使用注解,立刻享受开箱即用,什么配置都不用改。
-
写一个controller , 打上注解 @ExcelExport(filename = "users.xlsx")
java
@RestController
public class DemoController {
@ExcelExport(filename = "users.xlsx")
@GetMapping("/export")
public List<Map<String, Object>> exportUsers() {
List<Map<String, Object>> list = new ArrayList<>();
list.add(Map.of("id", 1, "name", "Alice"));
list.add(Map.of("id", 2, "name", "Bob"));
return list;
}
}
启动新项目,访问接口,下载 excel 功能可用。

理解自动装配作用
为了帮助理解自动装配的作用,最后作出一点说明,如果在 stater项目中没有编写 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
配置,那么新项目引入starter 依赖包需要在启动类添加包扫描的配置,因为spring 默认仅扫描启动类同级目录的包。自动装配中还写了一个配置类,能够确保Bean的实例化。
自动装配的价值在于实现了stater 的开箱即用,引入依赖不用实例化 bean 、包扫描等配置。

自动装配的本质
Spring Boot 自动装配就是通过条件化配置 ,把需要的 Bean 定义提前写好,然后在应用启动时根据运行环境(类路径、配置文件、已有 Bean)去"有选择地注册这些 Bean"。
自动装配Bean 和普通Bean注册相似,不过是多了一个条件化配置,减少了配置冲突。
关键组件
-
Configuration Class Parser(配置类解析器)
-
负责解析
@Configuration
和@Bean
,由ConfigurationClassPostProcessor
驱动。 -
AutoConfiguration Import Selector(选择器)
-
负责把**所有候选的自动配置类(spring.factories,AutoConfiguration.imports)**导入。
-
ConditionEvaluator(条件评估器)
-
评估
@ConditionalXXX
注解,决定配置类是否生效。 -
BeanDefinitionRegistry(Bean 定义注册器)
-
真正向容器注册 Bean 定义。
-
负责根据 BeanDefinition 实例化对象
-
ApplicationContext(上下文容器)
-
Bean 创建、依赖注入、生命周期管理都发生在这里。