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 个部分:
- 只应考虑对字段的调用而不是对局部变量的调用的检查
declaredIn
中检查方法是否应在具有 @Secured
-注释 的 class 中声明的部分
有办法实现吗?
第二部分有一个简单的解决方案:有
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();
}
}
我需要确保由 @Path
注释的 classes 仅调用由 @Secured
注释的 classes 中的方法。但只应检查字段上的方法调用(例如注入的 bean)。到目前为止我所拥有的是:
ArchRuleDefinition.classes().that()
.areAnnotatedWith(Path.class)
.or().areMetaAnnotatedWith(Path.class)
.should().onlyCallMethodsThat(are(declaredIn(!!!))
因此缺少 2 个部分:
- 只应考虑对字段的调用而不是对局部变量的调用的检查
declaredIn
中检查方法是否应在具有@Secured
-注释 的 class 中声明的部分
有办法实现吗?
第二部分有一个简单的解决方案:有
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();
}
}