AI 辅助 Java 开发实战:我用 Codex 写完了一个生产级项目
不是 AI 替代程序员,而是会 AI 的程序员替代不会 AI 的程序员。
一、介绍
2024-2025 年,AI 编码工具彻底改变了我的开发方式。
从最初的好奇尝试,到现在的日常依赖------我的代码量中约 60% 由 AI 生成,但我花在思考和审查上的时间反而增加了 40%。
这不是一篇工具教程。这是一篇实战复盘,记录我用 AI 辅助完成一个生产级 Java 项目的真实经验:踩过的坑、总结出的方法论、以及我认为每个 Java 开发者都应该知道的 AI 编码心法。
二、选对工具:我的 AI 编码工具箱
目前主流的 AI 编码工具有几个阵营:
| 工具 | 适合场景 | 我的评价 |
|---|---|---|
| GitHub Copilot | 日常补全、单元测试 | 补全准确率最高,但复杂逻辑生成不稳定 |
| Codex CLI / Claude Code | 复杂功能、重构、架构设计 | 理解上下文能力强,适合大块代码生成 |
| Cursor / Windsurf | 全流程开发 | Agent 模式强,但 Java 项目支持略弱 |
| Continue (VSCode 插件) | 自定义模型接入 | 灵活,可接本地模型,适合隐私敏感场景 |
如果你主要写 Java,我的建议是:Copilot 做主补全 + Codex/Claude 做复杂功能生成,两者互补。
三、实战项目背景
一个真实的微服务模块:订单履约中心(Order Fulfillment Center)
- 技术栈:Spring Boot 3.2 + MyBatis-Plus + RocketMQ + Redis
- 核心功能:订单拆分、库存预占、物流路由、状态机流转
- 代码量:约 1.5 万行
下面我用这个项目的真实片段,展示 AI 到底能帮到什么程度。
四、AI 编码的 5 个实战场景
场景 1:生成 POJO 和基础 CRUD ------ 最快最稳
这是 AI 最擅长的------重复、规律、模板化的工作。
我的提示词:
生成一个订单明细表 OrderItem 的实体类,包含字段:
id, orderId, skuId, productName, quantity, price, totalAmount, createdAt, updatedAt
使用 Lombok,MyBatis-Plus 注解,继承 BaseEntity
同时生成 Mapper 接口和 Service 类
AI 输出(节选):
java
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("order_item")
public class OrderItem extends BaseEntity {
@TableId(type = IdType.AUTO)
private Long id;
private Long orderId;
private Long skuId;
private String productName;
private Integer quantity;
@TableField("price")
private BigDecimal price;
private BigDecimal totalAmount;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
java
@Mapper
public interface OrderItemMapper extends BaseMapper<OrderItem> {
}
java
@Service
@RequiredArgsConstructor
public class OrderItemService extends ServiceImpl<OrderItemMapper, OrderItem> {
private final OrderItemMapper orderItemMapper;
public List<OrderItem> getByOrderId(Long orderId) {
return lambdaQuery().eq(OrderItem::getOrderId, orderId).list();
}
@Transactional
public void batchSave(List<OrderItem> items) {
saveBatch(items);
}
}
实战体会: 这种代码 AI 生成基本不需要改,直接复制粘贴就行。单文件生成准确率 > 95%。
场景 2:复杂业务逻辑 ------ AI 做框架,你做细节
这是最考验 prompt 能力的场景。看一个订单拆分逻辑:
我的提示词:
实现订单拆分逻辑:
1. 订单可能包含多个商品(OrderItem)
2. 根据商品所属的仓库(warehouseId)进行拆分
3. 同一仓库的商品合并为一个子订单
4. 每个子订单需要计算商品总金额、总数量
5. 如果某个商品库存不足,抛出 BusinessException("商品xxx库存不足")
6. 拆分完成后,保存子订单并发送 RocketMQ 消息
用策略模式实现,考虑到未来可能有其他拆分规则
AI 生成了一个完整的 SplitStrategy 接口 + WarehouseSplitStrategy 实现类。我只需要调整仓库分配的细节逻辑。
java
// AI 生成的核心策略
@Component
public class WarehouseSplitStrategy implements SplitStrategy {
@Override
public List<SubOrder> split(Order order, List<OrderItem> items) {
// 按 warehouseId 分组
Map<Long, List<OrderItem>> grouped = items.stream()
.collect(Collectors.groupingBy(OrderItem::getWarehouseId));
// 每组生成一个子订单
return grouped.entrySet().stream()
.map(entry -> createSubOrder(order, entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
}
private SubOrder createSubOrder(Order order, Long warehouseId, List<OrderItem> items) {
SubOrder subOrder = new SubOrder();
subOrder.setParentOrderId(order.getId());
subOrder.setWarehouseId(warehouseId);
subOrder.setStatus(SubOrderStatus.PENDING);
BigDecimal totalAmount = items.stream()
.map(OrderItem::getTotalAmount)
.reduce(BigDecimal.ZERO, BigDecimal::add);
subOrder.setTotalAmount(totalAmount);
subOrder.setTotalQuantity(
items.stream().mapToInt(OrderItem::getQuantity).sum()
);
subOrder.setItems(items);
return subOrder;
}
}
实战体会: 80% 的骨架代码 AI 能写对。但库存预占的锁逻辑 、事务边界 、异常处理的粒度------这些需要我亲手加。AI 不擅长你不知道它不知道的边界条件。
场景 3:单元测试 ------ AI 是真香
写单元测试是大部分开发者的痛点,AI 在这块是超强辅助。
我的提示词:
为 OrderSplitService.split(order) 方法写单元测试:
1. 用 Mockito + JUnit 5
2. 覆盖正常拆分场景
3. 覆盖商品跨仓库拆分场景
4. 覆盖库存不足异常场景
5. 覆盖订单为空异常场景
6. 验证 RocketMQ 消息是否正确发送
AI 生成的测试代码直接可运行度很高:
java
@ExtendWith(MockitoExtension.class)
class OrderSplitServiceTest {
@Mock
private OrderItemService orderItemService;
@Mock
private RocketMQProducer rocketMQProducer;
@InjectMocks
private OrderSplitService orderSplitService;
@Test
void shouldSplitOrderByWarehouse() {
// given
Order order = new Order();
order.setId(1L);
List<OrderItem> items = Arrays.asList(
createItem(1L, "SKU-A", 1001L, new BigDecimal("99.00"), 2),
createItem(2L, "SKU-B", 1002L, new BigDecimal("199.00"), 1),
createItem(3L, "SKU-C", 1001L, new BigDecimal("59.00"), 1)
);
// when
List<SubOrder> subOrders = orderSplitService.split(order, items);
// then
assertThat(subOrders).hasSize(2);
SubOrder warehouse1001 = subOrders.stream()
.filter(s -> s.getWarehouseId().equals(1001L))
.findFirst().orElseThrow();
assertThat(warehouse1001.getItems()).hasSize(2); // SKU-A + SKU-C
assertThat(warehouse1001.getTotalAmount())
.isEqualByComparingTo(new BigDecimal("257.00"));
SubOrder warehouse1002 = subOrders.stream()
.filter(s -> s.getWarehouseId().equals(1002L))
.findFirst().orElseThrow();
assertThat(warehouse1002.getItems()).hasSize(1); // SKU-B
verify(rocketMQProducer).send(any(Message.class));
}
}
实战体会: 测试覆盖率从 45% 飙升到 92%。AI 生成的测试覆盖面广 ,各种边界情况都考虑到了。我只需要检查断言是否符合预期逻辑。写测试的时间从 40% 降到 10%。
场景 4:代码审查 ------ AI 是第二双眼睛
把代码贴给 AI 做 Code Review:
java
// 这是我写的原始代码
public Order createOrder(CreateOrderRequest request) {
Order order = new Order();
order.setUserId(request.getUserId());
order.setTotalAmount(request.getItems().stream()
.map(i -> i.getPrice().multiply(BigDecimal.valueOf(i.getQuantity())))
.reduce(BigDecimal.ZERO, BigDecimal::add));
orderMapper.insert(order);
for (OrderItem item : request.getItems()) {
item.setOrderId(order.getId());
orderItemMapper.insert(item);
}
return order;
}
AI Review 结果:
- ⚠️ 事务问题 :
orderMapper.insert+orderItemMapper.insert没有事务保护,中间失败会导致数据不一致 - ⚠️ 金额精度 :
BigDecimal乘法要用setScale(2, RoundingMode.HALF_UP)确保精度 - ⚠️ 批量插入性能 :逐条 insert 在大数据量下慢,建议用
insertBatch - ⚠️ 空指针风险 :
request.getItems()可能为 null
修正后的代码:
java
@Transactional(rollbackFor = Exception.class)
public Order createOrder(CreateOrderRequest request) {
if (CollectionUtils.isEmpty(request.getItems())) {
throw new BusinessException("订单商品不能为空");
}
Order order = new Order();
order.setUserId(request.getUserId());
order.setTotalAmount(request.getItems().stream()
.map(i -> i.getPrice().multiply(BigDecimal.valueOf(i.getQuantity()))
.setScale(2, RoundingMode.HALF_UP))
.reduce(BigDecimal.ZERO, BigDecimal::add)
.setScale(2, RoundingMode.HALF_UP));
orderMapper.insert(order);
List<OrderItem> orderItems = request.getItems().stream()
.map(item -> {
OrderItem orderItem = new OrderItem();
BeanUtils.copyProperties(item, orderItem);
orderItem.setOrderId(order.getId());
return orderItem;
})
.collect(Collectors.toList());
orderItemService.saveBatch(orderItems);
return order;
}
实战体会: AI Review 发现了我忽略的 4 个问题。我现在任何代码合并前都会让 AI 过一遍,比自己两眼一抹黑看三遍管用。
场景 5:重构老代码 ------ AI 是真正的救星
一个 300 行的 OrderService 方法,if-else 嵌套 5 层。
我的提示词:
这个方法太长了,帮我重构:
1. 提取每个分支为独立方法
2. 用策略模式替代 if-else
3. 状态流转用枚举 + 状态机
4. 保持原有业务逻辑不变
5. 每个新方法都要有 JavaDoc
AI 把 300 行拆成了:
OrderStateMachine--- 状态机引擎OrderStateHandler接口 + 5 个实现类OrderEventPublisher--- 事件发布
代码量从 300 行变成了 600 行,但可维护性翻了几倍 。后来需求变更,加一个新状态只需要加一个 Handler 类,零改动旧代码。
五、我的 AI 编码心法(建议收藏)
心法 1:写好 Prompt 比写好代码更重要
markdown
❌ 差的 prompt:写一个订单服务
✅ 好的 prompt:
写一个 OrderService,需要:
1. 创建订单(校验库存→扣库存→保存订单→发消息)
2. 取消订单(校验状态→回滚库存→更新状态→发消息)
3. 使用 @Transactional 管理事务
4. 异常使用 BusinessException
5. 用 MyBatis-Plus 操作数据库
原则:给 AI 足够的信息,但不要让它猜。
心法 2:分步生成,不要一次搞定
不要这样:写一个完整的订单履约系统
要这样:
生成 Order 实体类生成 OrderMapper生成创建订单的业务逻辑生成单元测试
AI 在单步任务上准确率高,多步长任务容易跑偏。
心法 3:AI 生成,人工审查,缺一不可
这是我给自己定的铁律:
AI 写 → 我审 → 我改 → AI Review → 合入
每个环节不可跳过。AI 生成的代码至少有一个隐晦的 bug,这是我几十次实战验证的结论。可能是竞态条件、事务边界、或者是 JDK 版本的 API 差异。
心法 4:让 AI 做擅长的事
| AI 擅长 | AI 不擅长 |
|---|---|
| 生成样板代码 | 架构决策 |
| 写单元测试 | 领域建模 |
| 代码审查找漏 | 性能瓶颈定位 |
| 重构提取方法 | 全局一致性保证 |
| 解释遗留代码 | 安全漏洞防护 |
| 生成文档注释 | 业务规则挖掘 |
六、真实收益数据
这个项目做完后我统计了一下:
| 指标 | 使用 AI 前 | 使用 AI 后 | 提升 |
|---|---|---|---|
| 单功能开发周期 | 2.5 天 | 1 天 | 60% ↓ |
| 测试覆盖率 | 45% | 92% | 104% ↑ |
| 线上 Bug 率 | 平均 3 个/版本 | 0 个 | 追零 |
| 代码重复率 | 18% | 6% | 67% ↓ |
最意外的是 Bug 率下降 ------不是因为 AI 写的代码没 bug,而是因为我多出来的时间全用来做 Code Review 和测试了。
七、总结
AI 不会取代你,但会用 AI 的开发者会取代你。
我自己也走过弯路------一开始觉得 AI 写的代码不放心,每行都自己改;后来发现太浪费时间,开始信任 AI 处理模板化工作;现在找到了平衡点:AI 做执行,我做决策。
这不是偷懒,而是把精力花在真正有价值的事上------理解业务、设计架构、保障质量。
最后送各位三句话:
- 不要抗拒 AI --- 学起来,把它变成你的"超级实习生"
- 不要盲信 AI --- 它写的代码,你要负全责
- 不要停止思考 --- AI 能做 80% 的工作,但那 20% 的决策和判断,才是你的价值
互动话题:你平时用 AI 写代码吗?有没有什么神 prompt 或者踩坑经历?评论区见!