You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
austin/doc/CODE_OPTIMIZATION_RECOMMEND...

10 KiB

代码优化建议报告 (JDK 25 + Spring Boot 3.5.7)

📋 概述

本报告基于 Context7 最新文档和代码审查,针对 JDK 25 + Spring Boot 3.5.7 环境,提供代码质量、可读性和潜在 Bug 的优化建议。


🔴 严重问题(需要立即修复)

1. 异常处理不当 - printStackTrace()

文件: austin-support/src/main/java/com/java3y/austin/support/config/OkHttpConfiguration.java:85

问题:

  • 使用 e.printStackTrace() 输出到控制台,不利于生产环境日志管理
  • 方法返回 null,可能导致 NPE

修复建议:

@Bean
public SSLSocketFactory sslSocketFactory() {
    try {
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom());
        return sslContext.getSocketFactory();
    } catch (NoSuchAlgorithmException | KeyManagementException e) {
        log.error("Failed to create SSL socket factory", e);
        throw new IllegalStateException("Failed to initialize SSL context", e);
    }
}

影响:

  • ⚠️ 生产环境无法正确记录错误
  • ⚠️ 可能导致 Bean 创建失败,应用启动异常

2. 异常处理工具类混用

文件: austin-web/src/main/java/com/java3y/austin/web/exception/ExceptionHandlerAdvice.java:5

问题:

  • 使用了 org.assertj.core.util.Throwables(测试框架的工具类)
  • 应该使用 com.google.common.base.Throwables(项目其他地方统一使用)

修复建议:

import com.google.common.base.Throwables; // 替换 org.assertj.core.util.Throwables

影响:

  • ⚠️ 引入了测试依赖到生产代码
  • ⚠️ 可能导致依赖冲突

3. JDK 版本检测逻辑过时

文件: austin-support/src/main/java/com/java3y/austin/support/utils/ConcurrentHashMapUtils.java:17

问题:

  • 使用 System.getProperty("java.version").startsWith("1.8.") 检测 Java 8
  • JDK 25 环境下,版本格式为 2525.0.x,此逻辑失效

修复建议:

static {
    try {
        String version = System.getProperty("java.version");
        // JDK 9+ 格式: "9", "10", "11", "25" 等
        // JDK 8 格式: "1.8.0_xxx"
        IS_JAVA8 = version.startsWith("1.8.") || version.startsWith("1.7.");
    } catch (Exception ignore) {
        IS_JAVA8 = false; // 默认假设不是 Java 8
    }
}

或者直接移除该检查(因为项目已升级到 JDK 25:

public static <K, V> V computeIfAbsent(ConcurrentMap<K, V> map, K key, Function<? super K, ? extends V> func) {
    // JDK 9+ 已修复 computeIfAbsent 性能问题,直接使用
    return map.computeIfAbsent(key, func);
}

影响:

  • ⚠️ 可能导致性能优化逻辑错误执行
  • ⚠️ 不必要的代码复杂性

🟡 中等优先级问题(建议修复)

4. Null 安全检查不足

文件: austin-handler/src/main/java/com/java3y/austin/handler/action/SendMessageAction.java:27

问题:

  • taskInfo.getSendChannel() 可能返回 null
  • taskInfo.getReceiver() 可能返回 null 或空集合

修复建议:

@Override
public void process(ProcessContext<TaskInfo> context) {
    TaskInfo taskInfo = context.getProcessModel();
    Integer sendChannel = taskInfo.getSendChannel();
    
    if (sendChannel == null) {
        log.warn("Send channel is null, taskInfo: {}", taskInfo);
        return;
    }
    
    Set<String> receivers = taskInfo.getReceiver();
    if (CollUtil.isEmpty(receivers)) {
        log.warn("Receivers is empty, taskInfo: {}", taskInfo);
        return;
    }
    
    // ... 后续逻辑
}

5. 资源关闭可能异常

文件: austin-handler/src/main/java/com/java3y/austin/handler/receiver/redis/RedisReceiver.java:112

问题:

  • InterruptedException 被捕获后,在 catch 块中又捕获了新的异常,可能导致异常信息丢失

修复建议:

} catch (InterruptedException ex) {
    log.error("RedisReceiver#receiveMessage interrupted", ex);
    Thread.currentThread().interrupt();
    break;
}

6. 类型转换未进行空值检查

文件: austin-service-api-impl/src/main/java/com/java3y/austin/service/api/impl/action/send/SendAssembleAction.java:88

问题:

  • messageTemplate.get() 可能返回 null虽然已检查 isPresent但后续使用仍需注意

当前代码:

Optional<MessageTemplate> messageTemplate = messageTemplateDao.findById(messageTemplateId);
if (!messageTemplate.isPresent() || messageTemplate.get().getIsDeleted().equals(CommonConstant.TRUE)) {
    // ...
}
List<TaskInfo> taskInfos = assembleTaskInfo(sendTaskModel, messageTemplate.get());

建议: 使用 orElseThrow() 更清晰:

MessageTemplate template = messageTemplateDao.findById(messageTemplateId)
    .orElseThrow(() -> new CommonException(RespStatusEnum.TEMPLATE_NOT_FOUND));

if (template.getIsDeleted().equals(CommonConstant.TRUE)) {
    context.setNeedBreak(true).setResponse(BasicResultVO.fail(RespStatusEnum.TEMPLATE_NOT_FOUND));
    return;
}
List<TaskInfo> taskInfos = assembleTaskInfo(sendTaskModel, template);

🟢 代码质量和可读性优化

7. 使用构造函数注入替代字段注入

问题:

  • 项目中大量使用 @Autowired 字段注入151 处)
  • 不符合 Spring Boot 最佳实践(推荐构造函数注入)

建议:

  • 优先使用构造函数注入,提高可测试性和依赖清晰度
  • 对于可选依赖,可以使用 @Autowired(required = false)Optional<>

示例:

// 当前方式
@Service
public class SendMessageAction {
    @Autowired
    private HandlerHolder handlerHolder;
}

// 推荐方式
@Service
public class SendMessageAction {
    private final HandlerHolder handlerHolder;
    
    public SendMessageAction(HandlerHolder handlerHolder) {
        this.handlerHolder = handlerHolder;
    }
}

8. 使用 Lombok 简化代码

已优化文件: ExceptionHandlerAdvice.java 使用了 @Slf4j,但其他类仍使用 LoggerFactory

建议:

  • 统一使用 @Slf4j 注解
  • 使用 @RequiredArgsConstructor 替代手动构造函数注入

9. 字符串拼接优化

文件: austin-web/src/main/java/com/java3y/austin/web/exception/ExceptionHandlerAdvice.java:31

问题:

  • 使用 "\r\n" + errStackStr + "\r\n" 字符串拼接

建议:

  • JDK 25 可以使用字符串模板(需启用预览特性)
  • 或使用 String.format()MessageFormat

10. 使用 @PreDestroy@PostConstruct 的改进

文件: austin-handler/src/main/java/com/java3y/austin/handler/receipt/MessageReceipt.java

问题:

  • 使用 javax.annotation.*JSR-250在 JDK 11+ 中需要单独引入依赖

建议:

  • 在 JDK 25 环境下可以继续使用Spring Boot 已包含)
  • 或考虑使用 Spring 的生命周期回调接口

11. Switch 表达式可以进一步优化

已优化文件: SensWordsAction.java 已使用 switch 表达式

建议:

  • 检查其他文件是否还有传统 switch-case可统一优化

12. Optional 使用可以更优雅

已优化文件: Receiver.java 已使用 Optional.ifPresent()

建议:

  • 其他文件中的 Optional 使用可以继续优化
  • 避免 isPresent() + get() 的组合,使用 orElse(), orElseThrow()

🔵 Spring Boot 3.5.7 特性优化

13. 虚拟线程配置检查

已配置: application.properties 中已启用虚拟线程

建议验证:

# 确认虚拟线程已正确启用
spring.threads.virtual.enabled=true
spring.threads.virtual.scheduler.name-prefix=austin-virtual-

验证方法:

  • 检查线程名称是否包含 austin-virtual- 前缀
  • 使用 ProcessInfo.VirtualThreadsInfo 监控虚拟线程状态

14. 优雅关闭配置

已配置: server.shutdown=graceful

建议:

  • 确保所有线程池都注册到 ThreadPoolExecutorShutdownDefinition(已实现)
  • 验证关闭超时时间是否合理(当前 20 秒)

15. 配置属性验证

建议:

  • 使用 @ConfigurationProperties + @Valid 进行配置验证
  • 对于必需配置,使用 @NotNull@NotEmpty

📊 性能优化建议

16. 集合初始化容量优化

已优化: 部分文件已使用 new HashSet<>(size) 指定初始容量

建议:

  • 继续检查其他集合初始化,确保容量设置合理
  • 避免集合频繁扩容

17. Stream API 优化

建议:

  • 对于大数据量处理,考虑使用 parallelStream()(需注意线程安全)
  • 避免在 Stream 中进行复杂的数据库查询

18. Redis 操作优化

已优化: SimpleLimitService 使用 pipeline 批量操作

建议:

  • 继续检查其他 Redis 操作,优先使用批量操作
  • 考虑使用 Redis 事务或 Lua 脚本减少网络往返

🐛 潜在 Bug

19. 整数溢出风险

文件: austin-handler/src/main/java/com/java3y/austin/handler/deduplication/limit/SimpleLimitService.java:69

问题:

keyValues.put(key, String.valueOf(Integer.parseInt(inRedisValue.get(key)) + 1));

风险:

  • 如果计数超过 Integer.MAX_VALUE,会发生溢出

建议:

  • 使用 Long 类型
  • 或添加溢出检查

20. 字符编码处理

文件: austin-support/src/main/java/com/java3y/austin/support/utils/AustinFileUtils.java

建议:

  • 确保所有文件读取操作明确指定 UTF-8 编码
  • 避免使用系统默认编码

21. 日期时间处理

建议:

  • 检查是否所有日期时间操作都使用 java.time.* APIJDK 8+
  • 避免使用 java.util.DateCalendar

📝 总结

立即修复(高优先级)

  1. OkHttpConfiguration.java - 异常处理和日志
  2. ExceptionHandlerAdvice.java - 依赖替换
  3. ConcurrentHashMapUtils.java - JDK 版本检测逻辑

建议修复(中优先级)

  1. ⚠️ Null 安全检查增强
  2. ⚠️ 资源关闭异常处理
  3. ⚠️ Optional 使用优化

代码质量提升(低优先级)

  1. 💡 构造函数注入
  2. 💡 Lombok 优化
  3. 💡 Switch 表达式统一
  4. 💡 Spring Boot 3.5.7 特性充分利用

性能优化

  1. 集合初始化容量
  2. Stream API 优化
  3. Redis 批量操作

🚀 下一步行动

  1. 立即修复严重问题1-3
  2. 逐步优化中等优先级问题4-6
  3. 持续改进代码质量7-10
  4. 性能测试验证优化效果11-13

生成时间: 2024年 基于版本: JDK 25 + Spring Boot 3.5.7 检查工具: Context7 + 代码审查