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

手写一个最小 Starter:从 0 到能看懂

一、我们先定目标

我们做一个最简单的 starter,名字叫:ark-hello-starter

功能非常简单:

用户只要引入这个 starter,就能直接注入一个HelloService来调用。

像这样:

@Autowired private HelloService helloService;

然后:

System.out.println(helloService.sayHello());

输出:

hello from ark starter


二、你先理解:starter 到底拆成什么

最小 starter,核心就 3 样东西:

1)一个普通业务类

比如:HelloService

2)一个自动配置类

比如:HelloAutoConfiguration

3)一个配置注册文件

告诉 Spring Boot:

“启动时,把我的自动配置类也拿去加载”

三、整体结构先看懂

你可以先把 starter 理解成这个目录:

ark-hello-starter ├── src/main/java │ └── com/ark/starter │ ├── service │ │ └── HelloService.java │ └── autoconfigure │ └── HelloAutoConfiguration.java └── src/main/resources └── META-INF/spring └── org.springframework.boot.autoconfigure.AutoConfiguration.imports

四、第一步:写一个最普通的服务类

这个类本身一点都不神秘,就是个普通 Java 类:

package com.ark.starter.service; public class HelloService { public String sayHello() { return "hello from ark starter"; } }

五、第二步:写自动配置类

这一步才是 starter 的关键。

package com.ark.starter.autoconfigure; import com.ark.starter.service.HelloService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class HelloAutoConfiguration { @Bean public HelloService helloService() { return new HelloService(); } }

你先别管复杂的条件注解。

先只看本质:

自动配置类 = 启动时帮你把 Bean 放进 Spring 容器

也就是:

以前你要手动写:

@Configuration public class MyConfig { @Bean public HelloService helloService() { return new HelloService(); } }

现在 starter 帮你写好了。

六、第三步:注册自动配置类

这一步最重要,也是很多人第一次最陌生的地方。

在这个文件里写:

src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

内容:

com.ark.starter.autoconfigure.HelloAutoConfiguration

这一句的意思就是:

“Spring Boot 启动时,请把这个自动配置类也加载进来。”

七、到这里 starter 就成了

你现在回头看,其实 starter 没有你想象中那么玄学。

本质就是:

普通类
+ 自动配置类
+ 自动配置注册文件

八、再升级一步:加上 @ConditionalOnClass

现在我们把你前面学的东西塞进来。

比如改成这样:

package com.ark.starter.autoconfigure; import com.ark.starter.service.HelloService; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @ConditionalOnClass(HelloService.class) public class HelloAutoConfiguration { @Bean public HelloService helloService() { return new HelloService(); } }

虽然这个例子里HelloService.class本来就在 starter 里,条件判断意义不大,
但它是为了让你先看懂这个形式。

它表达的是:

只有类存在,配置才生效。

企业里常见的是判断第三方依赖,比如:

@ConditionalOnClass(RedisTemplate.class)

意思就是:

只有项目里引入了 Redis 相关类,我才自动配置 Redis 功能。

九、再升级一步:避免用户自己定义了同名 Bean

再加一个很常见的注解:

@ConditionalOnMissingBean

改成这样:

package com.ark.starter.autoconfigure; import com.ark.starter.service.HelloService; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @ConditionalOnClass(HelloService.class) public class HelloAutoConfiguration { @Bean @ConditionalOnMissingBean public HelloService helloService() { return new HelloService(); } }

这句话的意思:

如果用户自己没定义HelloService,我才给他自动创建。

这个非常重要,因为 starter 不能太霸道。

十、现在你彻底理解一下运行流程

用户项目一启动,Spring Boot 干了这些事:

1. 启动应用
2. 读取 AutoConfiguration.imports
3. 发现 HelloAutoConfiguration
4. 判断条件是否满足
5. 满足则执行 @Bean
6. 把 HelloService 放入容器
7. 用户就能直接 @Autowired

这就是 starter 的本质流程。

十一、用户项目怎么用这个 starter

假设你已经把ark-hello-starter打成 jar,并安装到本地仓库。

用户项目里只要加依赖:

<dependency> <groupId>com.ark</groupId> <artifactId>ark-hello-starter</artifactId> <version>1.0.0</version> </dependency>

然后直接写:

package com.demo.controller; import com.ark.starter.service.HelloService; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { private final HelloService helloService; public TestController(HelloService helloService) { this.helloService = helloService; } @GetMapping("/hello") public String hello() { return helloService.sayHello(); } }

访问:GET /hello

返回:hello from ark starter

十二、你现在会发现一件事

starter 其实不是“某种神秘技术”,它只是:

把别人本来要手动写的配置,提前封装好了。

所以它的价值是:

  • 降低接入成本
  • 统一技术方案
  • 自动完成初始化
  • 做成可插拔能力

十三、和 Android 经验怎么对齐

这块其实很好理解。

你可以把 starter 类比成:

Android 里的 SDK 接入包

比如你引一个网络库 SDK:

implementation "xxx-sdk"

然后它可能自动帮你:

  • 提供 API Client
  • 提供拦截器
  • 提供初始化逻辑
  • 提供默认配置

Spring Boot starter 也是这个意思,只不过它用的是:

  • 依赖
  • 自动配置
  • Spring Bean 容器

所以你可以把它理解成:

后端里的“自动初始化 SDK 包”

十四、为什么 starter 往往要拆成两部分

你以后会看到一些文章说:

  • xxx-spring-boot-starter
  • xxx-spring-boot-autoconfigure

这是因为企业里经常把它拆开。

1)starter

负责引依赖

2)autoconfigure

负责自动配置

你现在先不用纠结这个拆分。

你现阶段只要记住:

starter 核心一定绕不开自动配置类。


十五、给你一个最小可跑版本

我直接给你一套最简代码骨架,你以后回头抄都行。


1)HelloService.java

package com.ark.starter.service; public class HelloService { public String sayHello() { return "hello from ark starter"; } }

2)HelloAutoConfiguration.java

package com.ark.starter.autoconfigure; import com.ark.starter.service.HelloService; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @ConditionalOnClass(HelloService.class) public class HelloAutoConfiguration { @Bean @ConditionalOnMissingBean public HelloService helloService() { return new HelloService(); } }

3)AutoConfiguration.imports

com.ark.starter.autoconfigure.HelloAutoConfiguration

路径必须是:

src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports


十六、你现在最容易混乱的点,我直接帮你拆掉

误区1:starter 是不是特殊语法

不是。

它本质上还是:

  • 普通类
  • 配置类
  • 注册文件

误区2:没有 @ConditionalOnClass 就不是 starter

不是。

没有条件注解也能是 starter。

只是企业里一般都会加条件,避免乱加载。


误区3:starter 一定很复杂

不是。

最小 starter 非常简单。

复杂的是企业级 starter,会加上:

  • 配置参数绑定
  • 条件判断
  • 默认值
  • 多实现切换
  • 日志
  • 扩展点

十七、该掌握到什么程度

你现在不用追求“会写企业级 starter”。

你只要先到这一步就够了:

第一层

知道 starter 是什么

第二层

知道 starter 由什么组成

第三层

知道自动配置类怎么把 Bean 放进去

第四层

知道@ConditionalOnClass@ConditionalOnMissingBean为什么常出现

到这里,你就已经不是“starter 小白”了。


十八、最短记忆

我给你一句最短记忆法:

starter = 依赖入口 + 自动配置

再展开一点:

starter = 帮用户自动把某套功能接进 Spring 容器


十九、最后我帮你把这件事落到你当前阶段

现在不用急着真的去写一个完整 starter 发到项目里。
现在最重要的是:

先把这个骨架理解了,以后看到spring-boot-starter-webredis startermybatis starter,你脑子里就知道它们在干嘛。

这就已经值了。


下一篇:

《手写 Starter 进阶:@ConfigurationProperties 实战(支持 application.yml)》

这个一接上,你就会明白为什么很多 starter 可以这样用:

ark:
hello:
enabled: true
message: hello world

这一步就会更像真正企业里的 starter。

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

相关文章:

  • 考研复习Day 16 | 数据结构与算法 --树与二叉树(上)
  • AI Agent Harness Engineering 的部署架构:单体部署、分布式部署与混合云
  • 终极BT下载加速指南:每天更新的Tracker列表让你的下载速度翻倍
  • FastAPI 项目 PyInstaller 打包 exe 全踩坑根治教程(Windows 全电脑通用分发)
  • 企业云盘选型标准合同条款:数据归属/服务等级/SLA全解析
  • 探究分享从对话到执行:OpenTiny NEXT 如何重塑前端智能化开发范式
  • STM32 IAP升级踩坑实录:BootLoader跳转失败、向量表重置、Flash分区冲突,我是如何解决的?
  • ControlSizePyQt - PyQt 版本的统一尺寸和颜色管理系统
  • 网络工程师必看:H3C与华为认证体系的前世今生及备考选择指南
  • 淘一个二手铷原子钟并用起来的过程
  • 从卖不出去到月入15000,贵阳这两家公司凭什么让销售翻身? - 精选优质企业推荐官
  • 一文看懂推荐系统:排序09:Field-aware Factorization Machines (FFM) 的工业界冷思考:为何从FM到FFM的改进叫好不叫座?
  • uni-app怎么实现弹窗 uni-app自定义模态框遮罩层【代码】
  • ESP32上传图片到巴法云,除了HTTPClient,你还可以试试这个库
  • 频谱分析仪
  • Qt Quick项目实战:用KDDockWidgets 1.4.0为你的QML界面添加可拖拽停靠面板(附源码)
  • C语言学习日志
  • 学习分享数据结构对比
  • Spring Boot 自动装配原理(面试版 + 实战理解版)
  • 老年人扎堆学AI,背后藏着千亿级银发经济新蓝海
  • 别再让Quartus默认的1GHz时钟坑了你!手把手教你为FPGA点灯工程写SDC约束文件
  • 通风系统节能改造笔记:用PLC分段控制替代PID,稳定风压还省电(含现场数据对比)
  • 【2026年最新600套毕设项目分享】微信小程序的小说实体书商城(30106)
  • RKNN模型在RK3588上初始化失败?别慌,可能是你的虚拟环境和开发板版本对不上
  • AI开发-python-langchain框架(--pdf文件分页加载 )
  • Polkadot 技术栈地图 2026
  • 【计算机网络 实验报告6】路由选择协议
  • 从H264到H266:视频编码的‘乐高’块是如何越变越小的?一个动画演示看懂核心差异
  • 千问模型本地部署
  • 万字长文爆肝:彻底弄懂Linux文件系统(Ext2),从Inode、Block到Dentry核心机制全解析