De annotaties zijn al een tijdje ingeburgerd in Java en iedereen die ooit met Java 1.5 of hoger heeft gewerkt, zal het vertrouwde @-tje herkennen, maar hoe vaak heb je er nu een zelf gemaakt? Waarschijnlijk nooit, want dat is toch het domein van de Springs, Hibernates en andere frameworks in deze wereld. Hoe gaat het überhaupt in zijn werk? Het is namelijk geen onderdeel van een of ander certificaat.
Op internet zijn wel wat dingen te vinden over hoe annotaties te maken, maar daarbij valt me op dat er nooit wordt ingegaan op zogenaamde runtime annotaties, annotaties die je ook tijdens het runnen van jouw programma kunt gebruiken.
Annotaties zijn in feite niet meer dan interfaces:
public @interface Ranked {
String column() default "";
}
Er vallen wel een aantal dingen op; voor het keyword interface staat een @-tje en de property declaratie ziet er heel verschillend uit. Ook ben je wat beperkt in je typekeuze voor een property. Alleen primitieve types, String, Class, annotaties en enums mogen of een 1-dimensionale array hiervan. Geen objecten dus. In de praktijk is dit echter niet echt een belemmering.
Het keyword default geeft, geheel verwacht, een standaard waarde aan de property. Als je dit keyword weglaat, is deze property verplicht om in te vullen.
De overige configuratie kun je op de interface annoteren en zal ik even de vier nuttigste opties doornemen:
@Retention:
Dit geeft aan wanneer een annotatie beschikbaar is op de class. Dit kan zijn alleen tijdens build-time, tijdens compile-time of tijdens runtime. Zie de enum RetentionPolicy.
@Target
Dit geeft aan waar de annotatie geldig is, bv. op types, fields of methods. Zie de enum ElementType.
@Documented
Dit geeft aan of de annotatie ook wordt meegenomen met de Javadoc.
@Inherited
Dit geeft aan of de annotatie ook wordt doorgegeven via inheritance.
Onze annotatie zie er na configuratie er als volgt uit:
@Retention(value=RetentionPolicy.RUNTIME)
@Target(value={ElementType.TYPE})
@Documented
public @interface Ranked {
}
Dus kunnen we deze annotatie tijdens runtime nog steeds gebruiken en mag deze alleen op classes worden gebruikt. De @Documented spreekt vanzelf.
Nu is de annotatie klaar voor gebruik op de bekend manier:
/*
* Deze class is geranked.
*/
@Ranked
public class Product {
}
Nu moeten we ook nog wat met deze property gaan doen, want ook al lijkt Spring soms magisch, het werkt niet vanzelf. Onze magie zit bijvoorbeeld in de DAO, waar we entiteiten met @Ranked automatisch sorteren. (Ja, ik weet dat dit ook kan met @Sort kan)
if (persistentClass.isAnnotationPresent(Ranked.class)) {
return findByCriteriaOrdered(Order.desc(RANK));
}
Waar het hier om gaat is de method isAnnotationPresent van de class Class. Deze kijkt of een annotatie tijdens runtime (vandaar de RetentionPolicy) in de class aanwezig is. Als dat zo is, kun je daarmee iets doen, zoals hier gebeurd.