抽象类应定义在专用契约模块(如common-api),通过api依赖被下游继承,禁止混入实现逻辑;需配合接口形成双层契约,并发布至私仓供复用。

抽象类本身不“暴露接口”,而是通过设计契约、依赖管理与模块边界控制,让下游模块能安全、清晰地使用其定义的抽象层。关键不在“暴露”,而在“如何被正确引用和继承”。
明确抽象类的归属模块
抽象类应定义在提供通用能力的模块中(如 common-api 或 core-abstract),而非具体实现模块。这个模块只包含抽象类、接口、DTO、常量等契约性代码,不含业务逻辑或第三方实现。
- 模块命名建议带
-api或-contract后缀,例如user-api、payment-contract - 该模块的
build.gradle中不应引入spring-boot-starter等运行时依赖,仅声明compileOnly或api范围的依赖(如org.jetbrains:annotations) - 打包类型保持为
jar,且不包含任何main类或自动配置
用 Gradle 的 api/implementation 正确声明依赖关系
在 Gradle 多模块项目中,抽象层模块必须被下游模块以 api 方式依赖,才能让子类继承抽象类时不受编译错误影响。
- 假设
base-abstract模块定义了abstract class PaymentProcessor - 实现模块
alipay-impl需要这样声明依赖:
api project(':base-abstract')
// ✅ 这样,alipay-impl 中的 AlipayProcessor 才能继承 PaymentProcessor
// ❌ 若用 implementation,则子类继承会报 "Cannot resolve symbol" 错误
}
发布抽象层模块到私有 Maven 仓库
团队协作或跨项目复用时,抽象层模块需发布为可引用的 artifact,供其他项目通过坐标导入。
立即学习“Java免费学习笔记(深入)”;
- 在
base-abstract的build.gradle中应用maven-publish插件 - 配置
group(如com.example)、version(建议语义化版本,如1.2.0)、artifactId(如payment-contract) - 发布命令:
./gradlew :base-abstract:publish,推送至 Nexus/Artifactory 等私仓 - 下游项目即可用标准方式引用:
api 'com.example:payment-contract:1.2.0'
配合接口 + 抽象类双层契约设计
更稳健的做法是:抽象类实现一个公共接口,接口定义行为契约,抽象类提供默认实现和模板逻辑。这样既满足面向接口编程,又保留复用能力。
- 例如定义
PaymentService接口 →AbstractPaymentService抽象类 →AlipayService具体实现 - 接口放在
-api模块,抽象类也放在同一模块(或独立-abstract模块),确保调用方只需依赖接口,继承方才需依赖抽象类 - 避免把抽象类和具体实现混在一个模块里——这会破坏“对内隐藏细节,对外暴露接口”的原则


















