ArchUnit 介绍

是什么

ArchUnit 是一个专门用于 Java 架构测试的开源库,由德国 TNG Technology Consulting 公司开发维护。

核心理念:把架构约束写成代码,像跑单元测试一样验证架构是否被遵守。


解决什么问题

在实际项目中,架构规范往往只存在于文档和口头约定中:

"Controller 层不能直接调 Repository"
"Service 不能依赖 Web 层"
"util 包不能依赖 domain 包"

但这些约定没有任何强制力——开发者一忙就忘了,或者新来的人压根不知道。时间长了,架构腐化,依赖混乱。

ArchUnit 的解法:把这些规则写成测试代码,CI/CD 每次构建时自动验证,违规直接失败。


核心能力

能力 说明
包依赖检查 检查包之间的依赖关系是否合规
分层架构验证 验证 Controller → Service → Repository 单向依赖
循环依赖检测 自动发现包之间的循环引用
命名规范检查 检查类名、方法名是否符合约定
注解使用规范 某些注解只能用在特定包/类型上
继承/实现规范 检查接口实现、类继承关系约束
调用关系检查 某些类不允许被其他类调用

代码示例

1. 分层架构验证(最常用)

java

复制

@Test
public void 分层架构应遵守单向依赖() {
    JavaClasses classes = new ClassFileImporter()
        .importPackages("com.myapp");

    layeredArchitecture()
        .consideringAllDependencies()
        .layer("Controller").definedBy("..controller..")
        .layer("Service").definedBy("..service..")
        .layer("Repository").definedBy("..repository..")
        // Controller 只能被外部访问
        .whereLayer("Controller").mayNotBeAccessedByAnyLayer()
        // Service 只能被 Controller 访问
        .whereLayer("Service").mayOnlyBeAccessedByLayers("Controller")
        // Repository 只能被 Service 访问
        .whereLayer("Repository").mayOnlyBeAccessedByLayers("Service")
        .check(classes);
}

2. 命名规范检查

java

复制

@Test
public void Service类应以Service结尾() {
    classes()
        .that().resideInAPackage("..service..")
        .should().haveSimpleNameEndingWith("Service")
        .check(classes);
}

@Test
public void Controller类应该带RestController注解() {
    classes()
        .that().haveSimpleNameEndingWith("Controller")
        .should().beAnnotatedWith(RestController.class)
        .check(classes);
}

3. 禁止依赖检查

java

复制

@Test
public void Service层不能直接依赖Controller层() {
    noClasses()
        .that().resideInAPackage("..service..")
        .should().dependOnClassesThat()
        .resideInAPackage("..controller..")
        .check(classes);
}

4. 循环依赖检测

java

复制

@Test
public void 包之间不应存在循环依赖() {
    slices()
        .matching("com.myapp.(*)..")
        .should().beFreeOfCycles()
        .check(classes);
}

与主流框架集成

xml

复制

<!-- Maven 引入 -->
<dependency>
    <groupId>com.tngtech.archunit</groupId>
    <artifactId>archunit-junit5</artifactId>
    <version>1.3.0</version>
    <scope>test</scope>
</dependency>

支持:

  • JUnit 4 / JUnit 5(最常用)
  • TestNG
  • Spring Boot Test 无缝集成

技术原理

源码/字节码
    ↓
ClassFileImporter(字节码解析)
    ↓
JavaClasses(内存中的类模型)
    ↓
规则引擎(fluent API 描述规则)
    ↓
违规收集 → 断言失败 → 输出清晰报错信息

ArchUnit 通过直接分析 .class 字节码文件,不依赖源码,不需要运行时反射,性能好且精确。


适用场景

场景 描述
团队规范落地 新人入职规范自动检查,无需 Code Review 强制把关
微服务架构守护 确保各模块间依赖边界不被越界调用
遗留系统治理 梳理现有代码依赖关系,发现架构腐化点
CI/CD 卡口 架构违规直接阻断构建流水线

优缺点

优点 缺点
零侵入,纯测试代码 只支持 Java/Kotlin/Groovy(JVM 系语言)
上手简单,Fluent API 可读性强 规则需要人工维护
与 JUnit/CI 无缝集成 大型项目首次扫描略慢
报错信息清晰,定位准确 动态代理类可能误报,需要排除配置

一句话总结

ArchUnit 就是给架构设计加了一道自动化防火墙,让团队的架构约定不再只是口头承诺,而是每次构建都会自动执行的测试守卫。

特别适合技术规范落地难、团队协作经验不一致的中大型项目。有架构管理诉求的团队强烈推荐引入。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐