← [ BACK_TO_NOTES ]

Java 项目结构与分层

源码目录约定与包分层:如何让依赖方向稳定、测试与部署边界清晰。

#concept #growing #dev #java

[!info] related notes

Java 项目结构与分层

这个概念为什么出现

语言会了仍可能把代码堆成“大泥球”。项目结构回答:源码放哪、测试放哪、依赖朝哪指、模块如何拆。

[!abstract] 一句话理解 采用构建工具约定目录;用包/模块表达边界;本篇采用入口依赖应用、应用依赖领域、基础设施实现内层接口的组织方式,避免领域反向依赖 JDBC 等实现细节。

结构示例

场景:订单服务的包草图

src/main/java/shop/order/
  api/OrderController.java      # 入口适配
  app/PlaceOrderService.java    # 用例
  domain/Order.java             # 领域
  infra/JdbcOrderRepository.java # 基础设施
src/test/java/shop/order/...

这里画的是源码依赖方向,不是运行时调用顺序:

api → app → domain
infra → domain(实现接口)
app → domain 接口(不直接依赖 JDBC 细节)

应用通过接口调用,运行时仍可能执行 JdbcOrderRepository;外层启动/装配代码负责创建实现并注入应用。这种依赖倒置不会因目录命名而自动生效,需要访问控制、构建模块或依赖检查约束。

结合场景再看三个关注点

  1. 领域不依赖框架注解也可测(理想)。
  2. 接口按职责放在应用或领域侧,实现放 infra;不是每个类都需要额外抽接口。
  3. 测试镜像主包结构。

核心概念与准确模型

1. 标准目录

Maven 与 Gradle Java 插件默认使用 src/main/java、src/test/java,并分别提供 resources 目录。Java package 声明确定命名空间;目录与包名对齐是构建/工程约定,不是目录名自动决定访问权限。

2. 分层 vs 按功能

  • 按层:controller/service/repo 全局切
  • 按功能:order/ 下聚合层——扩展时常更清晰

3. 模块拆分

  • 多构建模块(如 order-domain/order-infra)、Java 包、JPMS module 和部署服务不是同一层边界,不应一一等同。
  • 控制循环依赖

边界情况与反直觉行为

  1. 过度微服务拆分早于边界清晰。
  2. 共享 kernel 变成新泥球。
  3. 测试只测框架装配不测领域。

常见误区

[!warning] 常见误区:utils 包垃圾桶 无主名责任的 util 膨胀是架构腐烂信号。

工程实践

  1. ArchUnit 等守护依赖方向(可选)。
  2. 公共库慎抽。
  3. README 写清模块职责。
  4. 与团队统一一种主风格。

本节总结

  • 目录约定 + 依赖方向
  • 功能包 + 分层思想
  • 为 Web/数据访问落地

自测题

  1. 为什么领域层不要直接依赖 JDBC 驱动类型?
  2. main/test 分离的收益?
参考答案
  1. 便于替换持久化与单测,避免基础设施细节泄漏。
  2. 生产产物不带测试代码,测试可依赖测试范围库。

延伸阅读与资料来源

资料类型支撑内容
Maven Standard Directory Layout官方目录约定
Gradle Java projects官方源集
创建于 2026/7/15 更新于 2026/10/6
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本