Archunit测试:类只能访问它们实现的接口


我有两个包,一个用于接口,另一个用于实现。我想将类的访问权限限制为只能访问它们实现的接口。说:
package com.interfaces
interface AI {
}
package com.interfaces
interface BI {
}
package com.impls
class A implements AI{
}
package com.impls
class B implements BI{
}

我已经有了一条规则来确保com.impls中的每个类实现com.interfaces中的一个接口:

ArchRuleDefinition.classes()
.that().resideInAPackage("com.impls..")
.should().implement(JavaClass.Predicates.resideInAPackage("com.interfaces.."))

现在我需要确保类只访问它实现的接口。如果这有帮助的话,我也可以依赖上面例子中的命名约定。我正在寻找类似的东西:

ArchRuleDefinition.classes()
.that().resideInAPackage("com.impls..")
.should().implement(JavaClass.Predicates.resideInAPackage("com.interfaces.."))
.andShould().onlyHaveDependentClassesThat().haveSimpleNameContaining("THE NAME OF THE IMPLEMENTING CLASS")

我们将在所有地方使用接口,并且将注入实现(Spring Boot(。但是一个实现不允许访问它没有实现的接口。所以AI可以访问A但不能访问B。BI可以访问B但不能访问A!另一方面,接口并不局限于实现。它们将用于其他软件包。

有没有一种方法可以重用规则第一部分的名称,或者在ArchUnit中以另一种方式限制访问?

如果您想防止A以外的任何类依赖于A等,您可以使用

ArchRuleDefinition.classes()
.that().resideInAPackage("com.impls..")
.should().implement(JavaClass.Predicates.resideInAPackage("com.interfaces.."))
.andShould(new ArchCondition<JavaClass>("not have other classes depending on them") {
@Override
public void check(JavaClass javaClass, ConditionEvents events) {
List<JavaClass> otherClassesThatDependOnJavaClass = javaClass.getDirectDependenciesToSelf().stream()
.map(Dependency::getOriginClass)
.filter(origin -> !origin.equals(javaClass))  // TODO: inner classes?
.collect(toList());
boolean satisfied = otherClassesThatDependOnJavaClass.isEmpty();
String message = satisfied
? "no other classes depend on " + javaClass.getName()
: otherClassesThatDependOnJavaClass.stream().map(JavaClass::getName)
.collect(joining(", ", "other classes depend on " + javaClass.getName() + ": ", ""));
events.add(new SimpleConditionEvent(javaClass, satisfied, message));
}
});

如果这是您的用例,您可能希望调整过滤器(请参阅TODO(以考虑内部类。

您要求的.filter(origin -> !origin.getSimpleName().contains(javaClass.getSimpleName()))很容易实现,但可能过于宽松。

最新更新