注解处理器可以作为一种变通办法,将某些语言功能纳入Java语言。
jOOQ还具有注解处理器,可帮助验证以下方面的SQL语法:
普通的SQL使用(SQL注入风险)
SQL方言支持(防止在MySQL上使用仅Oracle功能)
单元测试注解处理器
单元测试注解处理器比使用它们要棘手得多。您的处理器挂接到Java编译器并操纵已编译的AST(或执行其他操作)。如果要测试自己的处理器,则需要运行Java编译器的测试,但这在常规项目设置中很难做到,特别是如果给定测试的预期行为是编译错误。
假设我们有以下两个注解:
@interface A {}
@interface B {}
现在,我们想建立一个@A必须始终伴随的规则@B。例如:
// This must not compile
@A
class Bad {}
// This is fine
@A @B
class Good {}
我们将使用注解处理器来执行该操作:
class AProcessor implements Processor {
boolean processed;
private ProcessingEnvironment processingEnv;
@Override
public Set<String> getSupportedOptions() {
return Collections.emptySet();
}
@Override
public Set<String> getSupportedAnnotationTypes() {
return Collections.singleton("*");
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.RELEASE_8;
}
@Override
public void init(ProcessingEnvironment processingEnv) {
this.processingEnv = processingEnv;
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (TypeElement e1 : annotations)
if (e1.getQualifiedName().contentEquals(A.class.getName()))
for (Element e2 : roundEnv.getElementsAnnotatedWith(e1))
if (e2.getAnnotation(B.class) == null)
processingEnv.getMessager().printMessage(ERROR, "Annotation A must be accompanied by annotation B");
this.processed = true;
return false;
}
@Override
public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
return Collections.emptyList();
}
}
现在,这有效。我们可以通过将注解处理器添加到某些Maven编译器配置中并通过使用A和B注解几个类来轻松地手动进行验证。但是随后,有人更改了代码,我们没有注意到回归。我们该如何对它进行单元测试,而不是手动处理?
jOOR 0.9.10支持注解处理器
jOOR是我们在jOOQ内部使用的小开源反射库
jOOR有一个方便的API,可以javax.tools.JavaCompiler通过调用API Reflect.compile()。最新版本0.9.10现在带有一个可选CompileOptions参数,可以在其中注册注解处理器。
这意味着,我们现在可以编写一个非常简单的单元测试,如下所示
@Test
public void testCompileWithAnnotationProcessors() {
AProcessor p = new AProcessor();
try {
Reflect.compile(
"org.joor.test.FailAnnotationProcessing",
```
package org.joor.test;
@A
public class FailAnnotationProcessing {
}
```,
new CompileOptions().processors(p)
).create().get();
Assert.fail();
}
catch (ReflectException expected) {
assertTrue(p.processed);
}
Reflect.compile(
"org.joor.test.SucceedAnnotationProcessing",
```
package org.joor.test;
@A @B
public class SucceedAnnotationProcessing {
}
```,
new CompileOptions().processors(p)
).create().get();
assertTrue(p.processed);
}
太简单!永远不会在注解处理器中再进行回归!
最后,开发这么多年我也总结了一套学习Java的资料与面试题,如果你在技术上面想提升自己的话,可以关注我,可以加一下我的Java学习交流群:970917008,有时间记得帮我点下转发让跟多的人看到哦。