使用注解强制方法签名
Enforce method signature using annotations
我编写了一个自定义注释,用于查找可通过 IoT 平台调用的方法。这是一个方法级别的注释:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DirectMethod {
String value();
}
我在运行时查看了这个注解,要调用成功,预期的签名必须是:
@DeviceMethod("metod")
public ReturnType methodName(final String data) {...}
即 return 类型和输入参数至关重要。
当目标类型为 METHOD
时,是否有任何方法可以使注释为 "smart"?比如集成 IDE 警告等。或者我是否只需要在启动时手动处理每个注释,如果任何方法破坏了我的预期方法合同,启动过程就会失败?
是的,您可以编写注释处理器来验证您的调用,唯一的缺点是注释处理器需要传递给 javac(gradle 并且 maven 支持简单的语法来注册它们)所以有人可以只是不这样做,看不到任何 warnings/errors。
但除此之外,您需要做的就是创建特殊的注释和处理器,例如:
@SupportedAnnotationTypes("com.gotofinal.direct.DirectMethod")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class DirectAnnProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
TypeElement stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String");
TypeElement expectedReturnType = processingEnv.getElementUtils().getTypeElement("com.gotofinal.direct.ReturnType");
for (Element element : roundEnv.getElementsAnnotatedWith(DirectMethod.class)) {
if (! (element instanceof ExecutableElement)) {
processingEnv.getMessager().printMessage(Kind.ERROR, "Annotation should be on method.");
continue;
}
ExecutableElement executableElement = (ExecutableElement) element;
if (! executableElement.getReturnType().equals(expectedReturnType)) {
processingEnv.getMessager().printMessage(Kind.ERROR, "Method should return ReturnType");
}
List<? extends VariableElement> parameters = executableElement.getParameters();
if (parameters.size() != 1 && parameters.get(0).asType().equals(stringType)) {
processingEnv.getMessager().printMessage(Kind.ERROR, "Method should have single String argument");
}
}
return true; // no further processing of this annotation type
}
}
并在META-INF/services/javax.annotation.processing.Processor
文件中注册:
com.gotofinal.direct.DirectAnnProcessor
然后您可以将此类库添加到 maven/gradle 作为注释处理器,它应该会报告任何问题。在 gradle 中,必须使用 annotationProcessor "my:lib:0.1"
声明添加此类库。
我编写了一个自定义注释,用于查找可通过 IoT 平台调用的方法。这是一个方法级别的注释:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DirectMethod {
String value();
}
我在运行时查看了这个注解,要调用成功,预期的签名必须是:
@DeviceMethod("metod")
public ReturnType methodName(final String data) {...}
即 return 类型和输入参数至关重要。
当目标类型为 METHOD
时,是否有任何方法可以使注释为 "smart"?比如集成 IDE 警告等。或者我是否只需要在启动时手动处理每个注释,如果任何方法破坏了我的预期方法合同,启动过程就会失败?
是的,您可以编写注释处理器来验证您的调用,唯一的缺点是注释处理器需要传递给 javac(gradle 并且 maven 支持简单的语法来注册它们)所以有人可以只是不这样做,看不到任何 warnings/errors。
但除此之外,您需要做的就是创建特殊的注释和处理器,例如:
@SupportedAnnotationTypes("com.gotofinal.direct.DirectMethod")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class DirectAnnProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
TypeElement stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String");
TypeElement expectedReturnType = processingEnv.getElementUtils().getTypeElement("com.gotofinal.direct.ReturnType");
for (Element element : roundEnv.getElementsAnnotatedWith(DirectMethod.class)) {
if (! (element instanceof ExecutableElement)) {
processingEnv.getMessager().printMessage(Kind.ERROR, "Annotation should be on method.");
continue;
}
ExecutableElement executableElement = (ExecutableElement) element;
if (! executableElement.getReturnType().equals(expectedReturnType)) {
processingEnv.getMessager().printMessage(Kind.ERROR, "Method should return ReturnType");
}
List<? extends VariableElement> parameters = executableElement.getParameters();
if (parameters.size() != 1 && parameters.get(0).asType().equals(stringType)) {
processingEnv.getMessager().printMessage(Kind.ERROR, "Method should have single String argument");
}
}
return true; // no further processing of this annotation type
}
}
并在META-INF/services/javax.annotation.processing.Processor
文件中注册:
com.gotofinal.direct.DirectAnnProcessor
然后您可以将此类库添加到 maven/gradle 作为注释处理器,它应该会报告任何问题。在 gradle 中,必须使用 annotationProcessor "my:lib:0.1"
声明添加此类库。