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

ArchUnit如何限制实现类仅可访问自身实现的接口

ArchUnit实现类访问接口限制方案

方案1:基于命名约定实现(匹配你提到的类名关联逻辑)

如果遵循实现类名+I的接口命名规则(如A对应AI、B对应BI),可以直接通过自定义条件获取当前实现类名称,校验依赖接口的名称是否匹配:

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

ArchRule implAccessRuleByNaming = classes()
        .that().resideInAPackage("com.impls..")
        .should().implement(JavaClass.Predicates.resideInAPackage("com.interfaces.."))
        .andShould(new ArchCondition<JavaClass>("仅能访问名称包含自身类名的com.interfaces包接口") {
            @Override
            public void check(JavaClass implClass, ConditionEvents events) {
                String implSimpleName = implClass.getSimpleName();
                // 仅校验com.interfaces包下的接口依赖,跳过其他类型的依赖
                for (JavaClass dependency : implClass.getDependenciesFromSelf()) {
                    if (dependency.isInterface() && dependency.residesInAPackage("com.interfaces..")) {
                        if (!dependency.getSimpleName().contains(implSimpleName)) {
                            String msg = String.format("实现类[%s]违规访问未实现接口[%s]",
                                    implClass.getFullName(), dependency.getFullName());
                            events.add(SimpleConditionEvent.violated(implClass, msg));
                        }
                    }
                }
            }
        });

方案2:无命名依赖通用实现(直接校验实现关系)

不需要依赖命名约定,直接校验实现类依赖的接口是否是自身已经实现的接口,适配性更强:

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

ArchRule implAccessRule = classes()
        .that().resideInAPackage("com.impls..")
        .should().implement(JavaClass.Predicates.resideInAPackage("com.interfaces.."))
        .andShould(new ArchCondition<JavaClass>("仅能访问自身实现的com.interfaces包接口") {
            @Override
            public void check(JavaClass implClass, ConditionEvents events) {
                // 收集当前类所有允许访问的接口(自身实现的com.interfaces包下接口)
                Set<String> allowedItfNames = implClass.getAllInterfaces().stream()
                        .filter(itf -> itf.residesInAPackage("com.interfaces.."))
                        .map(JavaClass::getFullName)
                        .collect(Collectors.toSet());
                // 校验所有依赖
                for (JavaClass dependency : implClass.getDependenciesFromSelf()) {
                    if (dependency.isInterface() && dependency.residesInAPackage("com.interfaces..")) {
                        if (!allowedItfNames.contains(dependency.getFullName())) {
                            String msg = String.format("实现类[%s]违规访问未实现接口[%s],允许访问的接口为:%s",
                                    implClass.getFullName(), dependency.getFullName(), allowedItfNames);
                            events.add(SimpleConditionEvent.violated(implClass, msg));
                        }
                    }
                }
            }
        });

规则说明

  • 两种方案均仅限制com.impls包下的实现类的接口访问行为,不会影响其他包对com.interfaces下接口的正常调用
  • 自动过滤了非com.interfaces包的依赖校验,不影响实现类依赖JDK类、Spring组件、业务工具类等其他逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 06:54:03