Java Annotationen
Last updated
Was this helpful?
Last updated
Was this helpful?
Schnellübersicht: http://de.wikipedia.org/wiki/Annotation_%28Java%29
Annotationen wurden in Java 1.5 eingeführt. Vorgänger ausserhalb des Java-Kerns war XDoclet, mit dem man u. a. bei EJB 1.x und 2.x die Deployment-Deskriptoren (u. a. Database-Mapping) in den Java-Code schreiben konnte. Die Deployment-Deskriptoren wurden aus diesen Annotationen zur Compile-Zeit erzeugt. Dadurch war diese Information sehr nah beim Code. Annotationen bieten eine große Chance, die Semantik zu erhöhen und die Dokumentation zu verbessern.
Annotationen werden in Abhängigkeit der gesetzten (siehe entsprechende Annotationsdeklaration) zu unterschiedlichen Zeitpunkten ausgewertet
SOURCE: vor der Compile-Zeit, um dem Compiler wichtige Informationen zu liefern (z. B. @Deprecated, @Override) ... diese Annotationen schaffen es nicht in den Bytecode
es werden vom Compiler Warnungen angezeigt
es wird Code generiert
CLASS: zur Compilezeit/Deployzeit, um Code/Ressourcen zu generieren (z. B. Deployment-Deskriptoren) - im Bytecode enthalten
RUNTIME: zur Laufzeit (z. B. @Test von JUnit, @Transactional von Spring) - im Bytecode enthalten
mittels Reflection
ausgewertet.
Java stellt einige Annotationen (z. B. @Deprecated, @Override) selbst zur Verfügung, sie werden von Standard-Frameworks (Spring, Hibernate, ...) angeboten und jeder kann natürlich auch eigene schreiben.
Deklaration (Bestandteil des JUnit-Pakets):
Und so wird sie benutzt:
Somit muss eine Testklasse nicht mehr von TestCase erben, sondern kann den Vererbungsmechanismus für wichtigere Dinge (die Wiederverwendung eigener Testlogik) verwenden.
Folgende Annotationen verwendet man nur bei der Annotationsdeklaration (also innerhalb einer @interface Ressource)
@Documented: dann findet die Annotation auch ihren Weg in die JavaDoc
@Inherited: Annotation wird auch in abgeleitete Klassen vererbt (z. B. @Transactional von Spring)
@Retention: wann wird die Annotation ausgewertet (siehe RetentionPolicy)
RUNTIME
@Target: an welche Komponenten kann die Annotation gehangen werden (siehe Enumeration ElementType):
PACKAGE (z. B. @Deprecated)
TYPE (z. B: Spings @Transactional) - an eine Klasse
METHOD - an eine Methode
FIELD - an eine Member-Variable
ANNOTATION_TYPE - an eine Annotationsdeklaration (Wiederverwendung von Annotationslogik) - das steht dann beispielsweise in den Meta-Annotationen
...
siehe: http://download.oracle.com/javase/1,5.0/docs/guide/apt/GettingStarted.html
Auswertung durch
Schreiben eines AnnotationProcessor
, der dann beispielsweise vom APT Tool (Annotations Procession Tool - Bestandteil des JDK) ausgeführt wird
Reflection (nur für RUNTIME)
Wegen
"An important thing to note is the limitation of the annotation processing API — it can only be used to generate new files, not to change existing ones. The notable exception is the Lombok library which uses annotation processing as a bootstrapping mechanism to include itself into the compilation process and modify the AST via some internal compiler APIs. This hacky technique has nothing to do with the intended purpose of annotation processing [...]" (http://www.baeldung.com/java-annotation-processing-builder)
gibt es keine Möglichkeit, Prioritäten auf den Annotationen zu setzen, um bestimmte Annotationen vor anderen zu verarbeiten. Das könnte dann Sinn machen, wenn man zur Compilezeit weitere Annotationen hinzufügen wollte - das ist aber gar nicht vorgesehen.
Annotation-Processing erfolgt in sog. Runden, denn Annotation-Prozessoren zur Compile-Zeit erzeugen i. a. auch Code, der dann wiederum mit Annotation versehen sein können, die prozessiert werden müssen
"The annotation processing is done in multiple rounds. Each round starts with the compiler searching for the annotations in the source files and choosing the annotation processors suited for these annotations. Each annotation processor, in turn, is called on the corresponding sources. If any files are generated during this process, another round is started with the generated files as its input. This process continues until no new files are generated during the processing stage." (http://www.baeldung.com/java-annotation-processing-builder)
Wenn die Annotation bis in den Bytecode gelangt ist (RetentionPolicy.RUNTIME), dann kann sie zur Laufzeit per Reflection ausgewertet werden. Beispiel:
jede Java-Klasse kann zu einem Annotation Processor werden indem es das Interface implementiert
wenn der Vererbungsmechnismus noch nicht genutzt ist, kann man von ableiten