W Javie myślałem o przetwarzaniu adnotacji. Narzędzie apt skanuje plik źródłowy przed faktycznym przeanalizowaniem pliku źródłowego do polecenia javac.
Podczas kompilacji plików źródłowych wynik zostanie wydrukowany:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MyInterface {
int offset() default 0;
int last() default 100;
}
Fabryka procesorów:
public class MyInterfaceAnnotationProcessorFactory implements AnnotationProcessorFactory {
public Collection<String> supportedOptions() {
System.err.println("Called supportedOptions.............................");
return Collections.EMPTY_LIST;
}
public Collection<String> supportedAnnotationTypes() {
System.err.println("Called supportedAnnotationTypes...........................");
return Collections.singletonList("practiceproject.MyInterface");
}
public AnnotationProcessor getProcessorFor(Set<AnnotationTypeDeclaration> set, AnnotationProcessorEnvironment ape) {
System.err.println("Called getProcessorFor................");
if (set.isEmpty()) {
return AnnotationProcessors.NO_OP;
}
return new MyInterfaceAnnotationProcessor(ape);
}
}
Rzeczywisty procesor adnotacji:
public class MyInterfaceAnnotationProcessor implements AnnotationProcessor {
private AnnotationProcessorEnvironment ape;
private AnnotationTypeDeclaration atd;
public MyInterfaceAnnotationProcessor(AnnotationProcessorEnvironment ape) {
this.ape = ape;
atd = (AnnotationTypeDeclaration) ape.getTypeDeclaration("practiceproject.MyInterface");
}
public void process() {
Collection<Declaration> decls = ape.getDeclarationsAnnotatedWith(atd);
for (Declaration dec : decls) {
processDeclaration(dec);
}
}
private void processDeclaration(Declaration d) {
Collection<AnnotationMirror> ams = d.getAnnotationMirrors();
for (AnnotationMirror am : ams) {
if (am.getAnnotationType().getDeclaration().equals(atd)) {
Map<AnnotationTypeElementDeclaration, AnnotationValue> values = am.getElementValues();
int offset = 0;
int last = 100;
for (Map.Entry<AnnotationTypeElementDeclaration, AnnotationValue> entry : values.entrySet()) {
AnnotationTypeElementDeclaration ated = entry.getKey();
AnnotationValue v = entry.getValue();
String name = ated.getSimpleName();
if (name.equals("offset")) {
offset = ((Integer) v.getValue()).intValue();
} else if (name.equals("last")) {
last = ((Integer) v.getValue()).intValue();
}
}
//find the sum
System.err.println("Sum: " + ((last + 1 - offset) / 2) * (2 * offset + (last - offset)));
}
}
}
}
Następnie tworzymy plik źródłowy. prosta klasa korzystająca z adnotacji MyInterface:
@MyInterface(offset = 1, last = 1000)
public class Main {
@MyInterface
void doNothing() {
System.out.println("Doing nothing");
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
Main m = new Main();
m.doNothing();
MyInterface my = (MyInterface) m.getClass().getAnnotation(MyInterface.class);
System.out.println("offset: " + my.offset());
System.out.println("Last: " + my.last());
}
}
Procesor adnotacji jest kompilowany do pliku jar, a następnie narzędzie apt jest używane do kompilowania pliku źródłowego jako:
apt -cp "D:\Variance project\PracticeProject\dist\practiceproject.jar" -factory practiceproject.annotprocess.MyInterfaceAnnotationProcessorFactory "D:\Variance project\PracticeProject2\src\practiceproject2\Main.java"
Wyniki projektu:
Called supportedAnnotationTypes...........................
Called getProcessorFor................
Sum: 5000
Sum: 500500