You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用ArchUnit实现Repository仅被单个Service使用的架构规则?

实现ArchUnit规则:Repository不可在Service间共享

你需要实现的第二条规则可以通过自定义ArchCondition来检查每个Repository被Service引用的数量,确保每个Repository仅被一个Service使用。以下是完整的实现代码:

import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.Dependency;
import com.tngtech.archunit.lang.ArchCondition;
import com.tngtech.archunit.lang.ConditionEvents;
import com.tngtech.archunit.lang.SimpleConditionEvent;
import com.tngtech.archunit.lang.ArchRule;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;
import java.util.Set;
import java.util.stream.Collectors;

// 假设SUBPACKAGE_NAME_REPOSITORY和SUBPACKAGE_NAME_SERVICE是已定义的常量
@ArchTest
static final ArchRule repository_must_only_be_used_by_a_service =
        classes().that().resideInAnyPackage(SUBPACKAGE_NAME_REPOSITORY).should().onlyHaveDependentClassesThat()
                    .resideInAnyPackage(SUBPACKAGE_NAME_SERVICE);

@ArchTest
static final ArchRule repository_must_only_be_used_by_one_service =
        classes().that().resideInAnyPackage(SUBPACKAGE_NAME_REPOSITORY)
                .should(new ArchCondition<JavaClass>("be used by exactly one Service class") {
                    @Override
                    public void check(JavaClass repository, ConditionEvents events) {
                        // 筛选出直接依赖该Repository的Service类
                        Set<JavaClass> dependentServices = repository.getDirectDependenciesToSelf()
                                .stream()
                                .map(Dependency::getOriginClass)
                                .filter(service -> service.residesInAnyPackage(SUBPACKAGE_NAME_SERVICE))
                                .collect(Collectors.toSet());

                        // 检查Service数量是否为1
                        if (dependentServices.size() != 1) {
                            String violationMessage = String.format(
                                    "Repository %s 被 %d 个Service引用:%s",
                                    repository.getSimpleName(),
                                    dependentServices.size(),
                                    dependentServices.stream().map(JavaClass::getSimpleName).collect(Collectors.joining(", "))
                            );
                            events.add(SimpleConditionEvent.violated(repository, violationMessage));
                        }
                    }
                });

代码说明

  • 自定义ArchCondition:通过ArchCondition实现自定义检查逻辑,针对每个Repository类执行校验。
  • 筛选依赖的Service:使用getDirectDependenciesToSelf()获取所有直接依赖当前Repository的类,再过滤出属于Service包的类。
  • 数量校验:统计符合条件的Service数量,如果不等于1,则生成违规事件,明确提示违规的Repository和对应的Service列表。

注意事项

  • 如果需要考虑间接依赖(比如Service通过其他类间接引用Repository),可以将getDirectDependenciesToSelf()替换为getAllDependenciesToSelf(),但通常业务场景中Service直接注入Repository,直接依赖已经足够。
  • 确保SUBPACKAGE_NAME_REPOSITORY和SUBPACKAGE_NAME_SERVICE的包路径配置正确,比如"..repository.."或具体的包名前缀。

内容的提问来源于stack exchange,提问作者Olli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 09:31:33