开源项目(Get-jobs)优化
## Spring Framework 相关
### 1.1 Spring Bean 名称冲突
#### 问题描述
**时间**: 2025-10-21
**版本**: v1.0.19
**现象**: 应用启动失败,抛出异常
```
Cannot register alias 'taskExecutor' for name 'applicationTaskExecutor':
Alias would override bean definition 'taskExecutor'
```
#### 根本原因
自定义的 `TaskExecutor` 组件与 Spring 框架默认的异步任务执行器 bean 名称冲突:
- **框架保留名称**: `taskExecutor` (Spring @EnableAsync 相关)
- **框架保留名称**: `applicationTaskExecutor` (Spring Boot 自动配置)
- **自定义名称**: `taskExecutor` (冲突!)
#### 解决方案
**方案 1**: 显式指定 Bean 名称(推荐)
```java
@Configuration
public class TaskInfrastructureConfig {
@Bean(name = "infrastructureTaskExecutor") // 显式指定名称
public TaskExecutor taskExecutor(
TaskNotificationService notificationService,
UniqueTaskManager uniqueTaskManager,
List<TaskNotificationListener> listeners) {
return new TaskExecutor(notificationService, uniqueTaskManager, listeners);
}
}
```
**方案 2**: 使用 @Qualifier 注入
```java
@Service
public class TaskSchedulerService {
private final TaskExecutor taskExecutor;
public TaskSchedulerService(
@Qualifier("infrastructureTaskExecutor") TaskExecutor taskExecutor) {
this.taskExecutor = taskExecutor;
}
}
```
#### 最佳实践
1. ✅ **避免使用框架保留名称**,如 `taskExecutor`、`applicationTaskExecutor`
2. ✅ **使用更具体的命名**,如 `xxxTaskExecutor`、`yyyScheduler`
3. ✅ **显式指定 Bean 名称**,使用 `@Bean(name = "...")`
4. ✅ **依赖注入时使用 @Qualifier**,明确指定 Bean
#### 参考链接
- [Spring Boot Async 配置](https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.task-execution-and-scheduling)
- CHANGELOG: v1.0.19
---### 4.2 代码重复问题
#### 问题描述
**时间**: 2025-10-22
**版本**: v1.0.26
**现象**:
- 4 个平台服务各自实现配置转换逻辑
- 重复代码约 80 行 × 4 = 320 行
- 修改逻辑需要在 4 处同步
#### 解决方案
**抽象基类 + 模板方法模式**
```java
// 抽象基类 - 提供通用逻辑
public abstract class AbstractRecruitmentService implements RecruitmentService {
protected final ConfigService configService;
protected final UserProfileRepository userProfileRepository;
protected AbstractRecruitmentService(
ConfigService configService,
UserProfileRepository userProfileRepository) {
this.configService = configService;
this.userProfileRepository = userProfileRepository;
}
// 统一的配置转换逻辑
protected ConfigDTO convertConfigEntityToDTO(ConfigEntity entity) {
// 从 UserProfile 获取用户配置
UserProfile profile = userProfileRepository.findById(1L).orElse(null);
ConfigDTO dto = new ConfigDTO();
// 设置用户配置字段(6 个字段)
if (profile != null) {
dto.setSayHi(profile.getSayHi());
dto.setEnableAIGreeting(profile.getEnableAIGreeting());
// ...
}
// 设置平台配置字段
dto.setCityCodes(entity.getCityCodes());
dto.setFilterDeadHR(entity.getFilterDeadHR());
// ...
// 调用钩子方法,允许子类添加平台特定字段
populatePlatformSpecificFields(dto, entity);
return dto;
}
// 钩子方法 - 子类可覆写
protected void populatePlatformSpecificFields(ConfigDTO dto, ConfigEntity entity) {
// 默认实现为空
}
// 便捷方法 - 自动加载配置
protected ConfigDTO loadPlatformConfig() {
ConfigEntity entity = configService.loadByPlatformType(
getPlatform().getPlatformCode());
if (entity == null) {
log.warn("{}平台配置未找到", getPlatform().getName());
return null;
}
return convertConfigEntityToDTO(entity);
}
}
// 子类 - Boss 直聘
public class BossRecruitmentServiceImpl extends AbstractRecruitmentService {
public BossRecruitmentServiceImpl(
ConfigService configService,
UserProfileRepository userProfileRepository,
PlaywrightService playwrightService) {
super(configService, userProfileRepository);
this.playwrightService = playwrightService;
}
// 无需重写配置转换,直接使用基类方法
}
// 子类 - 猎聘(有特殊字段)
public class LiepinRecruitmentServiceImpl extends AbstractRecruitmentService {
// 覆写钩子方法,添加平台特定字段
@Override
protected void populatePlatformSpecificFields(ConfigDTO dto, ConfigEntity entity) {
// 添加猎聘特有的字段
dto.setPublishTime(entity.getPublishTime());
}
}
```
#### 重构收益
| 指标 | 重构前 | 重构后 | 改进 |
|-----|--------|--------|------|
| 重复代码 | 320 行 | 0 行 | -100% |
| 配置转换逻辑 | 4 处 | 1 处 | 集中管理 |
| 新增平台成本 | 高 | 低 | 继承即可 |
| 维护成本 | 高 | 低 | 一处修改 |
#### 设计模式
1. **模板方法模式**:
- 基类定义算法框架(`convertConfigEntityToDTO`)
- 子类实现特定步骤(`populatePlatformSpecificFields`)
2. **钩子方法**:
- 默认实现为空
- 子类按需覆写
- 保持灵活性
3. **DRY 原则**:
- Don't Repeat Yourself
- 消除重复代码
- 单一真实来源
#### 最佳实践
1. ✅ **识别重复代码模式**,及时抽象
2. ✅ **使用模板方法模式**,统一核心逻辑
3. ✅ **提供钩子方法**,支持特殊需求
4. ✅ **保持基类通用性**,不要过度抽象
5. ✅ **文档清晰**,说明扩展点
#### 参考链接
- [Template Method Pattern](https://refactoring.guru/design-patterns/template-method)
- CHANGELOG: v1.0.26
---
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Turnin
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果