Anpassen von Java-Compiler, der Ihre Annotation verarbeitet (Annotation Processing Tool)
1. Was ist Annotation Processing Tool (APT)?
Eine Situation entsteht:
Sie erstellen einige Annotation und benutzen sie in Ihrer Java Applikation. Die Annotaion hat einen von Ihnen gemachten Regel. Sie möchten, der Java compiler warnt während der Kompilierung den Fehler von der Verletzung des Regel. Und wenn Sie Eclipse zum Code Schreiben benutzen, möchten Sie Eclipse den Fehler auf die IDE informieren
Diese Dinge ist mit APT (Annotation Processing Tool).machtbar
Sie erstellen einige Annotation und benutzen sie in Ihrer Java Applikation. Die Annotaion hat einen von Ihnen gemachten Regel. Sie möchten, der Java compiler warnt während der Kompilierung den Fehler von der Verletzung des Regel. Und wenn Sie Eclipse zum Code Schreiben benutzen, möchten Sie Eclipse den Fehler auf die IDE informieren
Diese Dinge ist mit APT (Annotation Processing Tool).machtbar
Definition von APT:
APT (Java annotation processing tool) ist ein Instrument, damit Sie die Annotation auf die Soure Code Java behandeln. Alles Sie brauchen ist die Implementierung einer Annotation Processing
- Das Beispiel:
@PublicFinal ist eine Annotation von Ihnen. Ihr Regel ist, dass die Kommentar nur auf die Method oder field mit modifier public und final gemacht werden. Ber der Verletzung des Regel erscheint die Fehler Benachrichtigung bei der Zeitpunkt von der Kompilierung, gleichzeitig eine Nachricht in IDE.
2. Das Beispiel
Das ist das Beispiel, das ich in diesem Unterlagen vorstelle
Ihre Annotation
- @PublicFinal ist für die method oder field benutzt, die die Zugangsniveau (modifier) public và final.hat
- @Controller ist für die Kommentar der Class benutzt und der Name von Class müssen die Suffixe Controller haben.
- @Action ist für die Kommentar der String Type zurückgegebenen Method
Die Processor wie PublicFinalProcessor, ControllerProcessor, ActionProcesser führen die Aufgabe der Verletzung bei der Zeitpunkt von der Kompilierung durch, einschließen die Anzeige der Fehler in IDE Eclipse.
3. Project APTProcessor
Zuerst erstellen Sie ein Project
- APTProcessor
Action.java
package org.o7planning.ann;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Action {
}
Controller.java
package org.o7planning.ann;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface Controller {
}
PublicFinal.java
package org.o7planning.ann;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.SOURCE)
public @interface PublicFinal {
}
AcctionProccessor.java
package org.o7planning.aptprocessor;
import java.util.List;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic.Kind;
import org.o7planning.log.DevLog;
// Work with @Action
@SupportedAnnotationTypes({ "org.o7planning.ann.Action" })
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class ActionProcessor extends AbstractProcessor {
private Filer filer;
private Messager messager;
@Override
public void init(ProcessingEnvironment env) {
filer = env.getFiler();
messager = env.getMessager();
}
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment env) {
DevLog.log("\n\n");
DevLog.log(" ======================================================== ");
DevLog.log("#process(...) in " + this.getClass().getSimpleName());
DevLog.log(" ======================================================== ");
for (TypeElement ann : annotations) {
DevLog.log(" ==> TypeElement ann = " + ann);
List<? extends Element> es = ann.getEnclosedElements();
DevLog.log(" ====> ann.getEnclosedElements() count = " + es.size());
for (Element e : es) {
DevLog.log(" ========> EnclosedElement: " + e);
}
Element enclosingElement = ann.getEnclosingElement();
DevLog.log(" ====> ann.getEnclosingElement() = " + enclosingElement);
ElementKind kind = ann.getKind();
DevLog.log(" ====> ann.getKind() = " + kind);
Set<? extends Element> e2s = env.getElementsAnnotatedWith(ann);
DevLog.log(" ====> env.getElementsAnnotatedWith(ann) count = "
+ e2s.size());
for (Element e2 : e2s) {
DevLog.log(" ========> ElementsAnnotatedWith: " + e2);
DevLog.log(" - Kind : " + e2.getKind());
// @Action use for method only
// notify if misuse
if (e2.getKind() != ElementKind.METHOD) {
DevLog.log(" - Error!!!");
messager.printMessage(Kind.ERROR, "@Action using for method only ", e2);
} else {
// The name of the method is annotated by @Action
String methodName = e2.getSimpleName().toString();
// (ExecutableElement described for method, constructor,...)
ExecutableElement method = (ExecutableElement) e2;
DevLog.log(" - method : " + method);
TypeMirror retType = method.getReturnType();
DevLog.log(" -- method.getReturnType() : " + retType);
// @Action Only used for method returns the String
// Notify if misuse
if (!String.class.getName().equals(retType.toString())) {
DevLog.log(" - Error!!!");
messager.printMessage(Kind.ERROR,
"Method using @Action must return String", e2);
}
}
}
}
return true;
}
}
ControllProcessor.java
package org.o7planning.aptprocessor;
import java.util.List;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
import org.o7planning.log.DevLog;
// Apply for @Controller
@SupportedAnnotationTypes({ "org.o7planning.ann.Controller" })
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class ControllerProcessor extends AbstractProcessor {
private Filer filer;
private Messager messager;
@Override
public void init(ProcessingEnvironment env) {
filer = env.getFiler();
messager = env.getMessager();
}
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment env) {
DevLog.log("\n\n");
DevLog.log(" ======================================================== ");
DevLog.log("#process(...) in " + this.getClass().getSimpleName());
DevLog.log(" ======================================================== ");
for (TypeElement ann : annotations) {
DevLog.log(" ==> TypeElement ann = " + ann);
//
List<? extends Element> es = ann.getEnclosedElements();
DevLog.log(" ====> ann.getEnclosedElements() count = " + es.size());
for (Element e : es) {
DevLog.log(" ========> EnclosedElement: " + e);
}
Element enclosingElement = ann.getEnclosingElement();
DevLog.log(" ====> ann.getEnclosingElement() = " + enclosingElement);
ElementKind kind = ann.getKind();
DevLog.log(" ====> ann.getKind() = " + kind);
Set<? extends Element> e2s = env.getElementsAnnotatedWith(ann);
DevLog.log(" ====> env.getElementsAnnotatedWith(ann) count = "
+ e2s.size());
for (Element e2 : e2s) {
DevLog.log(" ========> ElementsAnnotatedWith: " + e2);
DevLog.log(" - Kind : " + e2.getKind());
// @Controller only use for Class
// Notify if misuse
if (e2.getKind() != ElementKind.CLASS) {
DevLog.log(" - Error!!!");
messager.printMessage(Kind.ERROR,
"@Controller using for class only ", e2);
} else {
// The name of the class is annotated by @Controller
String className = e2.getSimpleName().toString();
// @Controller using for class with suffix Controller
// Notify if misuse
if (!className.endsWith("Controller")) {
DevLog.log(" - Error!!!");
messager.printMessage(
Kind.ERROR,
"Class using @Controller must have suffix Controller", e2);
}
}
}
}
return true;
}
}
PublicFinalProcessor.java
package org.o7planning.aptprocessor;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
import org.o7planning.log.DevLog;
// Apply for @PublicFinal
@SupportedAnnotationTypes(value = { "org.o7planning.ann.PublicFinal" })
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class PublicFinalProcessor extends AbstractProcessor {
private Filer filer;
private Messager messager;
@Override
public void init(ProcessingEnvironment env) {
filer = env.getFiler();
messager = env.getMessager();
}
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment env) {
DevLog.log("\n\n");
DevLog.log(" ======================================================== ");
DevLog.log("#process(...) in " + this.getClass().getSimpleName());
DevLog.log(" ======================================================== ");
DevLog.log(" annotations count = " + annotations.size());
for (TypeElement ann : annotations) {
Set<? extends Element> e2s = env.getElementsAnnotatedWith(ann);
for (Element e2 : e2s) {
DevLog.log("- e2 = " + e2);
Set<Modifier> modifiers = e2.getModifiers();
// @PublicFinal only using for public & final
// Notify if misuse
if (!(modifiers.contains(Modifier.FINAL) && modifiers
.contains(Modifier.PUBLIC))) {
DevLog.log("- Error!!!");
messager.printMessage(Kind.ERROR,
"Method/field wasn't public and final", e2);
}
}
}
// All PublicFinal annotations are handled by this Processor.
return true;
}
}
DevLog.java
package org.o7planning.log;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class DevLog {
public static final String LOG_FILE = "C:/APT/log.txt";
public static void log(Object message) {
if (message == null) {
return;
}
// Make sure the path exists.
new File(LOG_FILE).getParentFile().mkdirs();
//
FileWriter writer = null;
try {
writer = new FileWriter(LOG_FILE, true);
writer.append(message.toString());
writer.append("\n");
writer.close();
} catch (IOException e) {
e.printStackTrace();
try {
writer.close();
} catch (IOException e1) {
}
}
}
}
Die Erklärung von Service
Erstellen Sie File javax.annotation.processing.Processor, die in dem Ordner META-INF/services wie das folgende Beispiel liegt:
javax.annotation.processing.Processor
org.o7planning.aptprocessor.PublicFinalProcessor
org.o7planning.aptprocessor.ActionProcessor
org.o7planning.aptprocessor.ControllerProcessor
Das project APTProcessor in die file jar einpacken:
Klicken Sie die Rechtmaustaste in Project und wählen Sie Export:
Export ist erfolgreich
4. Project APTTutorial
Erstellen Sie das Project APTTutorial:
Klicken Sie die Rechtmaustaste ins APTTutorial, wählen Sie Properties.
Melden Sie die Benutzung der vorher erstellten Bibliothek APTProccessor an
Melden Sie die Benutzung ihres Annotation Processor mit dem Compiler.an
Melden Sie die Position der Bibliothek Processor: an
Sie können Advanced.. klicken, um die mit dem Compiler registrierten Processor zu sehen
Klicken Sie OK zur Erledigung
Erstellen Sie einige Class, um Ihre Annotation und Processor zu testen
PublicFinalTest.java
package org.o7planning.tutorial.apttest;
import org.o7planning.ann.PublicFinal;
public class PublicFinalTest {
@PublicFinal
public final static int ABC = 100;
@PublicFinal
private static String MODULE_NAME = "APT";
}
Benachrichtigung des Fehler in IDE
TestActionController_01.java
package org.o7planning.tutorial.apttest;
import org.o7planning.ann.Action;
import org.o7planning.ann.Controller;
@Controller
public class TestActionController_01 {
@Action
public String exit() {
return null;
}
@Action
public void print() {
}
@Action
public int error() {
return 0;
}
}
TestActionController_02.java
package org.o7planning.tutorial.apttest;
import org.o7planning.ann.Controller;
@Controller
public interface TestActionController_02 {
public String close();
}
TestActionController.java
package org.o7planning.tutorial.apttest;
import org.o7planning.ann.Action;
import org.o7planning.ann.Controller;
@Controller
public class TestActionController {
@Action
public String login() {
return null;
}
}
Java Grundlagen
- Anpassen von Java-Compiler, der Ihre Annotation verarbeitet (Annotation Processing Tool)
- Java Programmierung für Team mit Eclipse und SVN
- Die Anleitung zu Java WeakReference
- Die Anleitung zu Java PhantomReference
- Komprimierung und Dekomprimierung in Java
- Konfigurieren von Eclipse zur Verwendung des JDK anstelle von JRE
- Java-Methoden String.format() und printf()
- Syntax und neue Funktionen in Java 8
- Die Anleitung zu Java Reguläre Ausdrücke
- Die Anleitung zu Java Multithreading Programming
- JDBC Driver Bibliotheken für verschiedene Arten von Datenbank in Java
- Die Anleitung zu Java JDBC
- Holen Sie sich die automatisch erhöhenden Wert der Spalte bei dem Insert eines Rekord, der JDBC benutzt
- Die Anleitung zu Java Stream
- Die Anleitung zu Java Functional Interface
- Einführung in Raspberry Pi
- Die Anleitung zu Java Predicate
- Abstrakte Klasse und Interface in Java
- Zugriffsmodifikatoren (Access modifiers) in Java
- Die Anleitung zu Java Enum
- Die Anleitung zu Java Annotation
- Vergleichen und Sortieren in Java
- Die Anleitung zu Java String, StringBuffer und StringBuilder
- Die Anleitung zu Java Exception
- Die Anleitung zu Java Generics
- Manipulieren von Dateien und Verzeichnissen in Java
- Die Anleitung zu Java BiPredicate
- Die Anleitung zu Java Consumer
- Die Anleitung zu Java BiConsumer
- Was ist erforderlich, um mit Java zu beginnen?
- Geschichte von Java und der Unterschied zwischen Oracle JDK und OpenJDK
- Installieren Sie Java unter Windows
- Installieren Sie Java unter Ubuntu
- Installieren Sie OpenJDK unter Ubuntu
- Installieren Sie Eclipse
- Installieren Sie Eclipse unter Ubuntu
- Schnelle lernen Java für Anfänger
- Geschichte von Bits und Bytes in der Informatik
- Datentypen in Java
- Bitweise Operationen
- if else Anweisung in Java
- Switch Anweisung in Java
- Schleifen in Java
- Die Anleitung zu Java Array
- JDK Javadoc im CHM-Format
- Vererbung und Polymorphismus in Java
- Die Anleitung zu Java Function
- Die Anleitung zu Java BiFunction
- Beispiel für Java Encoding und Decoding mit Apache Base64
- Die Anleitung zu Java Reflection
- Java-Remote-Methodenaufruf - Java RMI
- Die Anleitung zu Java Socket
- Welche Plattform sollten Sie wählen für Applikationen Java Desktop entwickeln?
- Die Anleitung zu Java Commons IO
- Die Anleitung zu Java Commons Email
- Die Anleitung zu Java Commons Logging
- Java System.identityHashCode, Object.hashCode und Object.equals verstehen
- Die Anleitung zu Java SoftReference
- Die Anleitung zu Java Supplier
- Java Aspect Oriented Programming mit AspectJ (AOP)
Show More
- Anleitungen Java Servlet/JSP
- Die Anleitungen Java Collections Framework
- Java API für HTML & XML
- Die Anleitungen Java IO
- Die Anleitungen Java Date Time
- Anleitungen Spring Boot
- Anleitungen Maven
- Anleitungen Gradle
- Anleitungen Java Web Services
- Anleitungen Java SWT
- Die Anleitungen JavaFX
- Die Anleitungen Oracle Java ADF
- Die Anleitungen Struts2 Framework
- Anleitungen Spring Cloud