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

Spring Boot 3.x 开发 Starter 快速上手体验,通过实践理解自动装配原理

本篇文章讲述 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 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 配置文件啥也不用写,追求快速上手。

开发流程:

  1. 编写一个注解 @ExcelExport
  2. 编写一个 AOP 切面, 切面内先让切入点执行方式,得到方法的返回值,使用 Apache POI 操作 excel 导出。
  3. controller 开发一个 exportUser 接口(理解成一个list查询接口),接口内模拟两条查询到的假数据。使用 @ExcelExport 便能实现导出功能。

功能开发好了我们再加入自动装配。

  1. 注解开发
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExcelExport {String filename() default "export.xlsx";
}
  1. 切面开发
/***  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() : "");}}// 写入 HttpServletResponseresponse.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;}
}
  1. controller 接口测试导出功能
@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)。

  1. @SpringBootApplication 注解内部有**@EnableAutoConfiguration**
  2. 加载自动配置类
  • @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 类(比如 DataSourceAutoConfigurationWebMvcAutoConfiguration)。

  1. 注册配置类
  • 这些自动配置类(其实就是 @Configuration 类)被 注册到 Spring 容器,但还没有立即实例化 Bean。
  1. 条件判断(筛选)
  • 每个自动配置类、或者其中的 Bean 方法,通常带有 @Conditional 系列注解:

  • @ConditionalOnClass:classpath 里有某个类才生效

  • @ConditionalOnMissingBean:用户没有自定义 Bean 才生效

  • @ConditionalOnProperty:配置文件里设置了某个属性才生效

  • Spring 会根据这些条件,决定哪些配置类/Bean 要真正装配。

  1. 注册 Bean 定义
  • BeanDefinitionRegistry (Bean的总入口) 负责把各种来源的 **Bean 定义信息转成 BeanDefinition ,**最后存到一个映射表里(BeanDefinitionMap)。
  • BeanFactory 负责根据 BeanDefinition 实例化对象。
  1. 容器刷新(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
开发实现
  1. 编写自动配置类 ExcelExportAutoConfiguration , 打上条件注解@ConditionalOnMissingBean(ExcelExportAspect.class) , 如果不存在ExcelExportAspect.class 才会加载这个配置类。
@Configuration
@ConditionalOnMissingBean(ExcelExportAspect.class)
public class ExcelExportAutoConfiguration {@Beanpublic ExcelExportAspect excelExportAspect() {return new ExcelExportAspect();}
}
  1. AutoConfiguration.imports 放入你想要自动装配的配置类
com.demoexcel.excelstater.config.ExcelExportAutoConfiguration

目录结构如下

生成 stater

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

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

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

引入 starter

刚刚生成了一个 starter 我们自己测试看效果。

  1. 创建一个Spring boot项目,项目名称: example-excel,基本 web 依赖。

  2. 引入 starter,新项目直接使用注解,立刻享受开箱即用,什么配置都不用改。

  3. 写一个controller , 打上注解 @ExcelExport(filename = “users.xlsx”)

@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 创建、依赖注入、生命周期管理都发生在这里。

http://www.dtcms.com/a/422666.html

相关文章:

  • 如何通过配置扩展服务函数的返回对象
  • 手工生成DuckDB 1.4版c++插件的简单步骤
  • linux进程生命周期
  • 单机游戏大全网站开发wordpress模板获取数据库
  • wap网站设计方案做一款网站注意啥
  • Flask项目中CSRF Token实现的解决方案
  • 使用 Kubernetes(k8s) 搭建 Redis 3 主 3 从集群教程
  • icejs状态管理store使用
  • Web开发 20
  • GPU计算效率提升:混合精度训练、并行优化、量化与VLLM实践
  • 做新闻类网站建站公司排名 软通
  • wordpress js 统计网站的seo是什么意思
  • 实用Excel学习资料包(含操作+函数+图表教程)
  • 开源AI智能名片链动2+1模式S2B2C商城小程序在公益课裂变法中的应用与影响研究
  • # vim中给变量添加双引号
  • wps word添加水印
  • 软考-系统架构设计师 应用程序与数据库的交互详细讲解
  • 改bug的一些体会
  • 安全对齐到底是什么
  • 专业VBA代码优化服务邀约‌,OFFICE excel计算优化,wrod报表生成
  • 织梦门户网站源码下载平面设计师的培训机构
  • 2025 AI 消费端变革:从生活助手到体验重构的全民浪潮
  • 【VUECLI】node.js打造自己的前端cli脚手架工具
  • 磁共振成像原理(理论)15:空间信息编码 (Spatial Information Encoding) -频率编码相位编码
  • 磐石网站seo手机nfc网站开发
  • 命名视图学习笔记
  • CentOS7安装OpenStack云计算平台框架
  • PyCharm中搭建PyTorch和YOLOv10开发环境
  • 无人机开源项目
  • 查看网站建设时间如何免费做网站优化