手写SpringBoot Starter(五):深度解析MyBatis Starter,学习大厂设计思想!🔬
系列文章第5篇(完结篇)| 共5篇
难度:⭐⭐⭐⭐ | 适合人群:想深入理解SpringBoot的高级开发者
📝 系列回顾
经过前面四篇的学习,我们已经:
- ✅ 第一篇: 理解了Starter的概念和价值
- ✅ 第二篇: 手写了第一个完整的Starter
- ✅ 第三篇: 实现了可插拔功能
- ✅ 第四篇: 添加了配置元数据智能提示
现在我们的Starter已经很完善了,但是…
💭 开场:一次技术分享会
时间: 周五下午
地点: 公司技术分享会
我: “经过一个月的努力,我完成了公司内部的通用Starter,大家可以直接引用使用…”(PPT展示)
架构师老王: “做得不错!不过我有个问题。”
我: “您说。” 😊
老王: “你这个Starter把所有功能都打包在一起了,如果有人只想用你的工具类,不想要自动配置呢?”
我: “这…” 😰(没想到这个问题)
老王: “你看MyBatis的设计,它分了两个包:mybatis-spring-boot-starter和mybatis-spring-boot-autoconfigure,为什么要这样设计?”
我: “emmm…不知道…” 😓
老王: “回去研究一下大厂的设计思想,下周再聊。”
回到工位,我陷入了沉思…
我: “为什么要拆成两个包?直接一个包不是更简单吗?” 🤔
经过一番研究后: “原来大有讲究!” 💡
🔍 第一问:MyBatis Starter的目录结构
查看Maven仓库
访问: https://mvnrepository.com/artifact/org.mybatis.spring.boot
看到两个包:
📦 mybatis-spring-boot-starter
└─ 用户引用这个
📦 mybatis-spring-boot-autoconfigure
└─ 真正的自动配置在这里
第一反应: “为啥要搞两个包?一个不够吗?” 🤨
下载源码查看
mybatis-spring-boot-starter 目录结构:
mybatis-spring-boot-starter/
├── pom.xml ← 只有pom.xml!
└── README.md
打开pom.xml:
<project>
<artifactId>mybatis-spring-boot-starter</artifactId>
<name>mybatis-spring-boot-starter</name>
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Spring Boot Starter JDBC -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- MyBatis Spring Boot AutoConfigure -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-autoconfigure</artifactId>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<!-- MyBatis Spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</dependency>
</dependencies>
</project>
发现: 只有依赖声明,没有任何Java代码!
恍然大悟: “原来Starter包只是一个依赖聚合器!” 💡
mybatis-spring-boot-autoconfigure 目录结构:
mybatis-spring-boot-autoconfigure/
├── src/main/java/
│ └── org/mybatis/spring/boot/autoconfigure/
│ ├── MybatisAutoConfiguration.java ← 自动配置类
│ ├── MybatisProperties.java ← 配置属性类
│ ├── ConfigurationCustomizer.java ← 配置定制器
│ └── SpringBootVFS.java ← VFS实现
├── src/main/resources/
│ └── META-INF/
│ ├── spring.factories ← 自动配置注册
│ └── spring-configuration-metadata.json ← 配置元数据
└── pom.xml
发现: 真正的自动配置代码都在这里!
🎯 第二问:为什么要拆成两个包?
设计哲学:关注点分离
Starter包职责:
📦 mybatis-spring-boot-starter
└─ 职责:依赖管理
├─ 聚合所有需要的依赖
├─ 统一版本管理
└─ 用户只需引入这一个
AutoConfigure包职责:
📦 mybatis-spring-boot-autoconfigure
└─ 职责:自动配置
├─ 包含自动配置类
├─ 包含配置属性类
└─ 包含spring.factories
优势分析
优势1:灵活性
场景: 用户想用MyBatis,但不想要自动配置
<!-- 方式A:引入Starter(自动配置) -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!-- 方式B:只引入核心库(手动配置) -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
</dependency>
如果不拆分: 用户无法选择!
优势2:可维护性
场景: 需要升级MyBatis版本
拆分设计:
<!-- Starter的pom.xml -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version> ← 只需改这里
</dependency>
不拆分: 自动配置代码和依赖混在一起,改起来容易出错
优势3:复用性
场景: 其他Starter也想用MyBatis的自动配置
<!-- 某个自定义Starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-autoconfigure</artifactId>
<!-- 只引入自动配置,不引入全部依赖 -->
</dependency>
如果不拆分: 无法单独复用自动配置逻辑
优势4:符合SpringBoot官方规范
SpringBoot官方建议:
Starter应该只包含依赖,不包含代码。
自动配置应该放在单独的模块中。
官方Starter结构:
spring-boot-starter-web ← Starter包(只有依赖)
spring-boot-autoconfigure ← AutoConfigure包(所有自动配置)
├─ WebMvcAutoConfiguration
├─ DispatcherServletAutoConfiguration
└─ ...
MyBatis遵循了这个规范!
对比图
【合并设计】一个包
mybatis-spring-boot-starter
├── 依赖声明
├── 自动配置代码
└── 配置元数据
↓
优点:简单
缺点:不灵活、难维护、不规范
【分离设计】两个包
mybatis-spring-boot-starter ← 用户引用
├── 只有依赖声明
mybatis-spring-boot-autoconfigure ← 真正实现
├── 自动配置代码
└── 配置元数据
↓
优点:灵活、好维护、符合规范
缺点:多一个包(但值得)
💻 第三问:深入MyBatis自动配置源码
MybatisProperties 配置属性类
位置: org.mybatis.spring.boot.autoconfigure.MybatisProperties
源码(简化版):
package org.mybatis.spring.boot.autoconfigure;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.Resource;
/**
* MyBatis配置属性
*/
@ConfigurationProperties(prefix = MybatisProperties.MYBATIS_PREFIX)
public class MybatisProperties {
public static final String MYBATIS_PREFIX = "mybatis";
/**
* Mapper XML文件位置
*/
private String[] mapperLocations;
/**
* 类型别名包
*/
private String typeAliasesPackage;
/**
* 类型处理器包
*/
private String typeHandlersPackage;
/**
* 检查配置文件是否存在
*/
private boolean checkConfigLocation = false;
/**
* 执行器类型:SIMPLE, REUSE, BATCH
*/
private ExecutorType executorType;
/**
* MyBatis配置文件位置
*/
private Resource configLocation;
/**
* 全局配置
*/
private Configuration configuration;
// Getter 和 Setter...
public String[] getMapperLocations() {
return mapperLocations;
}
public void setMapperLocations(String[] mapperLocations) {
this.mapperLocations = mapperLocations;
}
public String getTypeAliasesPackage() {
return typeAliasesPackage;
}
public void setTypeAliasesPackage(String typeAliasesPackage) {
this.typeAliasesPackage = typeAliasesPackage;
}
// ...其他getter/setter
}
学习点:
- 清晰的常量定义:
MYBATIS_PREFIX - 详细的字段注释: 每个字段都有说明
- 合理的默认值:
checkConfigLocation = false - 类型安全: 用枚举
ExecutorType而不是String
MybatisAutoConfiguration 自动配置类
位置: org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
源码(简化版):
package org.mybatis.spring.boot.autoconfigure;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.*;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ResourceLoader;
import javax.sql.DataSource;
/**
* MyBatis自动配置类
*/
@Configuration
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration {
private final MybatisProperties properties;
private final ResourceLoader resourceLoader;
public MybatisAutoConfiguration(
MybatisProperties properties,
ResourceLoader resourceLoader) {
this.properties = properties;
this.resourceLoader = resourceLoader;
}
/**
* 创建SqlSessionFactory
*/
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
factory.setDataSource(dataSource);
// 设置配置文件位置
if (this.properties.getConfigLocation() != null) {
factory.setConfigLocation(this.properties.getConfigLocation());
}
// 设置Mapper位置
if (this.properties.getMapperLocations() != null) {
factory.setMapperLocations(
this.resourceLoader.getResources(this.properties.getMapperLocations())
);
}
// 设置类型别名包
if (StringUtils.hasText(this.properties.getTypeAliasesPackage())) {
factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
}
return factory.getObject();
}
/**
* 创建SqlSessionTemplate
*/
@Bean
@ConditionalOnMissingBean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
ExecutorType executorType = this.properties.getExecutorType();
if (executorType != null) {
return new SqlSessionTemplate(sqlSessionFactory, executorType);
} else {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
}
关键注解深度解析
注解1:@ConditionalOnClass
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
作用: 只有当这些类在classpath中存在时,才加载这个配置类
原理:
// SpringBoot会检查
Class.forName("org.apache.ibatis.session.SqlSessionFactory");
// 如果抛异常(类不存在),就不加载配置类
使用场景: 避免在没有MyBatis依赖时加载配置
注解2:@ConditionalOnSingleCandidate
@ConditionalOnSingleCandidate(DataSource.class)
作用: 只有当Spring容器中有且仅有一个DataSource(或有Primary标记的DataSource)时才生效
为什么需要? MyBatis需要数据源,没有数据源或多个数据源会出问题
注解3:@AutoConfigureAfter
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
作用: 在DataSourceAutoConfiguration之后再执行
为什么? MyBatis依赖DataSource,必须先有数据源再配置MyBatis
配置顺序:
1. DataSourceAutoConfiguration ← 先配置数据源
2. MybatisAutoConfiguration ← 再配置MyBatis
注解4:@ConditionalOnMissingBean
@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) {
作用: 如果容器中没有SqlSessionFactory,才创建
好处: 允许用户自定义SqlSessionFactory覆盖默认实现
spring.factories 注册文件
位置: META-INF/spring.factories
内容:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.mybatis.spring.boot.autoconfigure.MybatisLanguageDriverAutoConfiguration,\
org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration
注意: 注册的是autoconfigure包中的配置类,不是starter包
🎨 第四问:SpringBoot官方的设计
官方Starter结构
以spring-boot-starter-web为例:
📦 spring-boot-starter-web
└─ pom.xml(只有依赖声明)
├─ spring-boot-starter
├─ spring-boot-starter-json
├─ spring-boot-starter-tomcat
├─ spring-web
└─ spring-webmvc
📦 spring-boot-autoconfigure
└─ 所有自动配置类
├─ web/
│ ├─ WebMvcAutoConfiguration
│ ├─ DispatcherServletAutoConfiguration
│ └─ ErrorMvcAutoConfiguration
├─ data/
│ ├─ redis/RedisAutoConfiguration
│ └─ jpa/HibernateJpaAutoConfiguration
└─ ...上百个自动配置类
特点:
- 所有官方Starter都只包含依赖
- 所有自动配置统一放在
spring-boot-autoconfigure模块 - 一个
spring.factories注册所有自动配置
为什么官方要统一管理?
优势:
- 统一版本: 所有自动配置版本一致
- 统一测试: 一次测试覆盖所有配置
- 统一发布: 一次发布所有Starter
- 避免冲突: 不会出现版本不兼容问题
劣势:
- 包体积大:
spring-boot-autoconfigure包含所有配置 - 升级影响大: 改一个配置需要重新发布整个包
结论: 对于SpringBoot这种基础框架,优势远大于劣势!
🏗️ 第五问:如何选择设计方案?
方案对比
方案A:单包设计(我们目前的)
hello-spring-boot-starter
├── src/main/java/
│ ├── HelloService.java
│ ├── HelloProperties.java
│ └── HelloAutoConfiguration.java
├── src/main/resources/
│ └── META-INF/spring.factories
└── pom.xml
适用场景:
- ✅ 简单的Starter(1-3个配置类)
- ✅ 个人项目或小团队
- ✅ 不需要单独复用自动配置
方案B:两包设计(MyBatis的)
hello-spring-boot-starter
└── pom.xml(只有依赖)
hello-spring-boot-autoconfigure
├── src/main/java/
│ ├── HelloService.java
│ ├── HelloProperties.java
│ └── HelloAutoConfiguration.java
├── src/main/resources/
│ └── META-INF/spring.factories
└── pom.xml
适用场景:
- ✅ 复杂的Starter(5+个配置类)
- ✅ 企业级项目
- ✅ 需要给其他Starter复用
- ✅ 想遵循SpringBoot官方规范
方案C:统一管理(SpringBoot官方的)
company-spring-boot-autoconfigure
├── module-a/
├── module-b/
└── module-c/
company-spring-boot-starter-a
└── pom.xml
company-spring-boot-starter-b
└── pom.xml
适用场景:
- ✅ 公司统一技术栈
- ✅ 多个相关Starter
- ✅ 需要统一版本管理
决策树
你的Starter是什么情况?
│
├─ 个人学习/简单工具
│ └─ 选择:方案A(单包) ⭐
│
├─ 企业内部使用/功能复杂
│ └─ 选择:方案B(两包) ⭐⭐
│
└─ 公司技术中台/多个Starter
└─ 选择:方案C(统一管理) ⭐⭐⭐
💻 第六问:改造我们的Starter(方案B)
项目结构改造
创建两个Maven模块:
hello-spring-boot/ ← 父项目
├── pom.xml ← 父pom
├── hello-spring-boot-starter/ ← Starter模块
│ └── pom.xml
└── hello-spring-boot-autoconfigure/ ← AutoConfigure模块
├── src/main/java/
├── src/main/resources/
└── pom.xml
父pom.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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>hello-spring-boot</artifactId>
<version>2.0.0</version>
<packaging>pom</packaging>
<name>Hello Spring Boot</name>
<description>Hello Starter Parent</description>
<!-- 子模块 -->
<modules>
<module>hello-spring-boot-autoconfigure</module>
<module>hello-spring-boot-starter</module>
</modules>
<!-- 继承SpringBoot父项目 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.10</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 依赖管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>hello-spring-boot-autoconfigure</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
autoconfigure模块的pom.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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父项目 -->
<parent>
<groupId>com.example</groupId>
<artifactId>hello-spring-boot</artifactId>
<version>2.0.0</version>
</parent>
<artifactId>hello-spring-boot-autoconfigure</artifactId>
<name>Hello Spring Boot AutoConfigure</name>
<description>Auto-configuration for Hello</description>
<dependencies>
<!-- SpringBoot核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 配置元数据处理器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- 校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
starter模块的pom.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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父项目 -->
<parent>
<groupId>com.example</groupId>
<artifactId>hello-spring-boot</artifactId>
<version>2.0.0</version>
</parent>
<artifactId>hello-spring-boot-starter</artifactId>
<name>Hello Spring Boot Starter</name>
<description>Starter for Hello</description>
<dependencies>
<!-- SpringBoot核心 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 引入AutoConfigure模块 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>hello-spring-boot-autoconfigure</artifactId>
</dependency>
</dependencies>
</project>
注意: Starter模块的pom.xml非常简洁,只包含依赖声明!
代码迁移
将所有Java代码移到autoconfigure模块:
hello-spring-boot-autoconfigure/src/main/java/com/example/autoconfigure/
├── HelloService.java
├── HelloProperties.java
├── HelloAutoConfiguration.java
├── HelloMarker.java
└── EnableHello.java
spring.factories也在autoconfigure模块:
hello-spring-boot-autoconfigure/src/main/resources/META-INF/
└── spring.factories
starter模块什么都不放:
hello-spring-boot-starter/
└── pom.xml ← 只有这一个文件!
打包发布
# 在父项目目录下执行
cd hello-spring-boot
mvn clean install
会同时打包两个模块:
[INFO] --- Installing hello-spring-boot-autoconfigure-2.0.0.jar ---
[INFO] --- Installing hello-spring-boot-starter-2.0.0.jar ---
[INFO] BUILD SUCCESS
使用方式
用户只需引入starter:
<dependency>
<groupId>com.example</groupId>
<artifactId>hello-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
Maven会自动传递依赖:
hello-spring-boot-starter
└─ hello-spring-boot-autoconfigure
└─ spring-boot-starter
效果和之前完全一样,但结构更专业! ✨
🎓 第七问:企业级Starter最佳实践总结
实践1:命名规范
✅ 推荐命名:
{company}-{module}-spring-boot-starter
{company}-{module}-spring-boot-autoconfigure
示例:
alibaba-druid-spring-boot-starter
alibaba-druid-spring-boot-autoconfigure
❌ 不推荐:
my-starter
custom-boot-starter
实践2:版本管理
<!-- 使用统一的父pom管理版本 -->
<parent>
<groupId>com.example</groupId>
<artifactId>company-dependencies</artifactId>
<version>1.0.0</version>
</parent>
<!-- 或使用dependencyManagement -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>company-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
实践3:文档完善
必须提供:
- README.md: 快速开始指南
- 配置说明: 所有配置项详细说明
- 使用示例: 常见场景代码示例
- 更新日志: CHANGELOG.md
- FAQ: 常见问题解答
示例README.md结构:
# Hello Spring Boot Starter
## 快速开始
### 1. 添加依赖
```xml
<dependency>
<groupId>com.example</groupId>
<artifactId>hello-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
```
### 2. 配置
```yaml
hello:
enabled: true
prefix: Hello
```
### 3. 使用
```java
@Autowired
private HelloService helloService;
```
## 配置项说明
| 配置项 | 类型 | 默认值 | 说明 |
|-------|------|--------|------|
| hello.enabled | boolean | true | 是否启用 |
| hello.prefix | String | Hello | 前缀 |
## 更新日志
### 2.0.0 (2024-01-20)
- 拆分为两个模块
- 添加配置校验
### 1.0.0 (2024-01-01)
- 初始版本
实践4:测试覆盖
必须测试:
- 自动配置测试: 验证Bean是否正确注册
- 条件注解测试: 验证各种条件是否生效
- 配置测试: 验证配置是否正确读取
- 集成测试: 在真实项目中测试
示例测试:
@SpringBootTest
@TestPropertySource(properties = {
"hello.enabled=true",
"hello.prefix=Test"
})
class HelloAutoConfigurationTest {
@Autowired(required = false)
private HelloService helloService;
@Test
void testAutoConfiguration() {
assertNotNull(helloService, "HelloService应该被自动注册");
assertEquals("Test World !", helloService.sayHello("World"));
}
}
实践5:向后兼容
升级时要考虑:
- 配置项不要轻易删除: 标记为
@Deprecated - 默认值不要轻易改: 可能影响现有项目
- API不要破坏性变更: 提供兼容层
- 提供迁移指南: 告诉用户如何升级
示例:
@ConfigurationProperties(prefix = "hello")
public class HelloProperties {
private String prefix = "Hello";
/**
* @deprecated 使用 prefix 替代
*/
@Deprecated
private String oldPrefix;
public String getPrefix() {
// 兼容旧配置
if (prefix == null && oldPrefix != null) {
return oldPrefix;
}
return prefix;
}
}
实践6:监控与日志
添加启动日志:
@Configuration
public class HelloAutoConfiguration {
private static final Logger log = LoggerFactory.getLogger(HelloAutoConfiguration.class);
@Bean
public HelloService helloService(HelloProperties properties) {
log.info("Hello Starter 自动配置成功");
log.info("配置信息: prefix={}, suffix={}",
properties.getPrefix(),
properties.getSuffix());
return new HelloService(properties.getPrefix(), properties.getSuffix());
}
}
添加健康检查(可选):
@Component
public class HelloHealthIndicator implements HealthIndicator {
@Override
public Health health() {
// 检查服务状态
return Health.up()
.withDetail("status", "Hello service is running")
.build();
}
}
🎉 系列总结
我们学到了什么?
第一篇:Starter基础
- ✅ Starter是SpringBoot的"套餐"机制
- ✅ 解决配置地狱问题
- ✅ 理解命名规范
第二篇:手写Starter
- ✅ 创建配置属性类
- ✅ 编写自动配置类
- ✅ 配置spring.factories
- ✅ 打包测试
第三篇:可插拔实现
- ✅ 配置文件开关
- ✅ 自定义注解开关
- ✅ 学习Zuul设计
第四篇:配置元数据
- ✅ 自动生成元数据
- ✅ 实现智能提示
- ✅ 配置校验
第五篇:设计思想
- ✅ Starter和AutoConfigure分离
- ✅ 深入MyBatis源码
- ✅ 企业级最佳实践
从入门到精通路线图
Level 1: 入门 ⭐
└─ 能看懂Starter,知道怎么用
Level 2: 初级 ⭐⭐
└─ 能写简单的Starter(单包)
Level 3: 中级 ⭐⭐⭐
└─ 能实现可插拔Starter,添加配置元数据
Level 4: 高级 ⭐⭐⭐⭐
└─ 能设计两包结构,遵循最佳实践
Level 5: 专家 ⭐⭐⭐⭐⭐
└─ 能设计企业级技术中台,统一管理多个Starter
恭喜你,看完这个系列,你已经达到Level 4了! 🎉
💡 下一步学习建议
1. 深入SpringBoot源码
推荐阅读:
SpringApplication.run()启动流程AutoConfigurationImportSelector自动装配原理@Conditional条件注解实现原理ConfigurationPropertiesBindingPostProcessor配置绑定原理
2. 研究优秀开源Starter
推荐研究:
- MyBatis Starter: 经典的两包设计
- Druid Starter: 阿里出品,配置丰富
- PageHelper Starter: 简洁实用
- Swagger Starter: 文档生成
- Dubbo Starter: 服务治理
3. 实战项目
建议实现:
- 日志Starter: 统一日志格式和输出
- Redis Starter: 封装常用Redis操作
- OSS Starter: 对象存储统一接口
- 短信Starter: 多渠道短信发送
- 权限Starter: 基于注解的权限控制
4. 参与开源
- 给优秀的Starter项目提PR
- 在GitHub上开源自己的Starter
- 写技术博客分享经验
🤔 最后的思考题
问题1: 如果你要为公司设计一套统一的技术栈Starter,会包含哪些模块?
问题2: SpringBoot 3.x 和 2.x 的Starter有什么区别?如何做兼容?
问题3: 如何监控Starter的使用情况(哪些项目在用、配置了什么参数)?
欢迎在评论区讨论! 💭
💬 写在最后
从第一篇到现在,我们一起:
- 👨💻 手写了完整的Starter
- 🔧 实现了可插拔功能
- 💎 添加了配置元数据
- 🔬 深入分析了源码
- 📚 总结了最佳实践
这个系列到这里就完结了!
如果这个系列对你有帮助,请:
- 👍 点赞支持
- ⭐ 收藏备用
- 🔄 转发分享
- 💬 评论交流
感谢一路陪伴,我们下个系列再见! 👋
深度解析MyBatis Starter设计
360

被折叠的 条评论
为什么被折叠?



