ArchUnit:仅检查字段方法调用

ArchUnit: Check only field method-calls

我需要确保由 @Path 注释的 classes 仅调用由 @Secured 注释的 classes 中的方法。但只应检查字段上的方法调用(例如注入的 bean)。到目前为止我所拥有的是:

ArchRuleDefinition.classes().that()
        .areAnnotatedWith(Path.class)
        .or().areMetaAnnotatedWith(Path.class)
        .should().onlyCallMethodsThat(are(declaredIn(!!!))

因此缺少 2 个部分:

有办法实现吗?

第二部分有一个简单的解决方案:有

import com.tngtech.archunit.core.domain.JavaClass;
import com.tngtech.archunit.core.domain.properties.HasOwner.Functions.Get;

import static com.tngtech.archunit.core.domain.properties.CanBeAnnotated.Predicates.annotatedWith;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes;

你可以使用

    classes()
            .that().areMetaAnnotatedWith(Path.class)
            .should().onlyCallMethodsThat(
                    Get.<JavaClass>owner().is(annotatedWith(Secured.class))
                            .as("are defined in classes annotated with @Secured")
            );

请注意 areMetaAnnotatedWith 还包括自 ArchUnit 0.17.0 以来的直接注释。如果您还想测试构造函数调用,可以将 onlyCallMethodsThat 替换为 onlyCallCodeUnitsThat.


不幸的是,我不认为第一部分可以用当前版本解决ArchUnit 0.23.1: You can rewrite the above rule to test each JavaMethodCall, which is more specific than the called JavaMethod:

    noClasses()
            .that().areMetaAnnotatedWith(Path.class)
            .should().callMethodWhere(describe("owner is not @Secured",
                methodCall ->
                    !methodCall.getTargetOwner().isAnnotatedWith(Secured.class)
            ));

JavaMethodCall#getOrigin(), you can find the JavaCodeUnit 发生方法调用的位置,但这不包括有关调用该方法的对象的信息。

如果我没理解错的话,你要区分以下几种情况:

@Secured
class SecuredOwner {
    void method() {
    }
}

class NotSecuredOwner {
    void method() {
    }
}

@Path
class ThisShouldBeOkay {
    SecuredOwner securedOwner = new SecuredOwner();

    void call_secured_method_on_field() {
        securedOwner.method();
    }

    void call_not_secured_method_on_local_variable() {
        new NotSecuredOwner().method();
    }
}