203 lines
5.7 KiB
Markdown
203 lines
5.7 KiB
Markdown
# Spring Boot 重构演示项目
|
||
|
||
## 项目简介
|
||
|
||
这个项目演示了如何处理Spring Boot项目中被多处引用的类的重构问题。通过适配器模式和门面模式,实现了从单体架构到分离架构的平滑过渡。
|
||
|
||
## 问题场景
|
||
|
||
原始的`User`类承担了太多职责:
|
||
- 用户基础信息(姓名、邮箱、电话等)
|
||
- 员工工作信息(部门、职位、薪资等)
|
||
- 系统安全信息(状态、登录记录等)
|
||
|
||
多个服务类都在操作这个`User`类:
|
||
- `UserManagementService` - 基础用户管理
|
||
- `HRService` - 人事管理
|
||
- `SecurityService` - 安全管理
|
||
- `NotificationService` - 通知服务
|
||
|
||
## 重构方案
|
||
|
||
### 新架构设计
|
||
|
||
将原始的`User`类拆分为三个独立的实体:
|
||
|
||
1. **UserProfile** - 用户基础信息
|
||
- 姓名、邮箱、电话、地址等个人信息
|
||
|
||
2. **EmployeeInfo** - 员工工作信息
|
||
- 部门、职位、薪资、入职时间等
|
||
|
||
3. **UserSecurity** - 用户安全信息
|
||
- 账户状态、登录记录、失败次数等
|
||
|
||
### 关键设计模式
|
||
|
||
1. **适配器模式 (Adapter Pattern)**
|
||
- `UserAdapter` 接口定义新旧实体转换规范
|
||
- `UserAdapterImpl` 实现具体转换逻辑
|
||
|
||
2. **门面模式 (Facade Pattern)**
|
||
- `UserFacadeService` 提供统一的操作接口
|
||
- 隐藏内部复杂的实体关系
|
||
|
||
3. **配置驱动切换**
|
||
- 通过配置文件控制使用哪个版本的架构
|
||
- 支持运行时切换,无需修改代码
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
src/main/java/com/example/refactor/
|
||
├── entity/
|
||
│ ├── User.java # 原始User实体
|
||
│ └── v2/
|
||
│ ├── UserProfile.java # 新架构:用户基础信息
|
||
│ ├── EmployeeInfo.java # 新架构:员工信息
|
||
│ └── UserSecurity.java # 新架构:安全信息
|
||
├── repository/
|
||
│ ├── UserRepository.java # 原始Repository
|
||
│ └── v2/
|
||
│ ├── UserProfileRepository.java
|
||
│ ├── EmployeeInfoRepository.java
|
||
│ └── UserSecurityRepository.java
|
||
├── service/
|
||
│ ├── UserManagementService.java # 原始服务
|
||
│ ├── HRService.java
|
||
│ ├── SecurityService.java
|
||
│ ├── NotificationService.java
|
||
│ ├── UserManagementServiceV2.java # 新架构服务
|
||
│ ├── HRServiceV2.java
|
||
│ ├── SecurityServiceV2.java
|
||
│ ├── NotificationServiceV2.java
|
||
│ └── v2/
|
||
│ └── UserFacadeService.java # 门面服务
|
||
├── adapter/
|
||
│ ├── UserAdapter.java # 适配器接口
|
||
│ └── UserAdapterImpl.java # 适配器实现
|
||
├── controller/
|
||
│ └── UserController.java # REST API
|
||
└── config/
|
||
└── DataInitializer.java # 数据初始化
|
||
```
|
||
|
||
## 运行项目
|
||
|
||
### 1. 使用原始架构 (V1)
|
||
|
||
```bash
|
||
# 编译项目
|
||
mvn clean compile
|
||
|
||
# 运行项目(默认使用V1架构)
|
||
mvn spring-boot:run
|
||
```
|
||
|
||
### 2. 使用新架构 (V2)
|
||
|
||
#### 方法一:修改配置文件
|
||
编辑 `application.yml`:
|
||
```yaml
|
||
app:
|
||
user:
|
||
architecture: v2
|
||
```
|
||
|
||
#### 方法二:使用命令行参数
|
||
```bash
|
||
mvn spring-boot:run -Dspring-boot.run.arguments="--app.user.architecture=v2"
|
||
```
|
||
|
||
#### 方法三:使用配置文件
|
||
```bash
|
||
mvn spring-boot:run -Dspring-boot.run.arguments="--spring.profiles.active=v2"
|
||
```
|
||
|
||
## API 测试
|
||
|
||
### 查看当前架构
|
||
```bash
|
||
curl http://localhost:8080/api/users/architecture
|
||
```
|
||
|
||
### 创建用户
|
||
```bash
|
||
curl -X POST http://localhost:8080/api/users \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"name":"测试用户","email":"test@example.com","phone":"13800138000"}'
|
||
```
|
||
|
||
### 查看所有用户
|
||
```bash
|
||
curl http://localhost:8080/api/users
|
||
```
|
||
|
||
### 更新员工信息
|
||
```bash
|
||
curl -X PUT http://localhost:8080/api/users/1/employee \
|
||
-H "Content-Type: application/json" \
|
||
-d '{"department":"研发部","position":"架构师","salary":20000}'
|
||
```
|
||
|
||
### 查看部门员工
|
||
```bash
|
||
curl http://localhost:8080/api/users/department/技术部
|
||
```
|
||
|
||
## 重构优势
|
||
|
||
### 1. 职责分离
|
||
- 每个实体类职责单一,易于理解和维护
|
||
- 减少了类之间的耦合度
|
||
|
||
### 2. 扩展性强
|
||
- 新增功能时只需修改相关的实体和服务
|
||
- 不会影响其他模块的功能
|
||
|
||
### 3. 向后兼容
|
||
- 通过适配器模式保证API兼容性
|
||
- 可以渐进式迁移,降低风险
|
||
|
||
### 4. 配置驱动
|
||
- 支持运行时切换架构
|
||
- 便于A/B测试和灰度发布
|
||
|
||
### 5. 数据库优化
|
||
- 可以针对不同实体进行数据库优化
|
||
- 支持分表分库等高级特性
|
||
|
||
## 迁移策略
|
||
|
||
### 阶段一:准备阶段
|
||
1. 创建新的实体类和Repository
|
||
2. 实现适配器和门面服务
|
||
3. 创建新版本的业务服务
|
||
|
||
### 阶段二:并行运行
|
||
1. 通过配置开关控制使用哪个版本
|
||
2. 在测试环境验证新架构的正确性
|
||
3. 逐步在生产环境进行灰度测试
|
||
|
||
### 阶段三:完全迁移
|
||
1. 将所有流量切换到新架构
|
||
2. 清理旧代码和数据结构
|
||
3. 优化新架构的性能
|
||
|
||
## 注意事项
|
||
|
||
1. **数据一致性**:在迁移过程中要确保数据的一致性
|
||
2. **性能考虑**:新架构可能涉及多表查询,需要优化性能
|
||
3. **事务管理**:跨多个实体的操作需要合理的事务边界
|
||
4. **监控告警**:增加监控来及时发现问题
|
||
|
||
## 总结
|
||
|
||
这个演示项目展示了如何通过设计模式和架构重构来解决单体类的问题。关键在于:
|
||
|
||
1. **渐进式重构**:不是一次性替换,而是逐步迁移
|
||
2. **保持兼容性**:通过适配器模式确保API不变
|
||
3. **配置驱动**:通过配置控制切换,降低风险
|
||
4. **职责分离**:将复杂的类拆分为职责单一的类
|
||
|
||
这种方法可以应用到任何需要重构复杂类的场景中。 |