1. diel - Annotation processor v Jave - Úvod do anotácií
Vitajte u prvej lekcie kurzu, v ktorom sa zoznámime s anotáciami v
Jave. Porozumieme tak označením ako @Deprecated
,
@FunctionalInterface
a ďalším "zavináčům" v kóde.
Vysvetlíme si, čo to anotácie je, ako sa používa a prečo môže byť
prínosné vytvoriť si svoju vlastnú. Ďalej sa pozrieme, ako sa dajú
anotácie spracovať aj iným spôsobom - už vo fáze kompilácie kódu. Reč
bude o Java Annotation Processor. Hovoríte si, na čo je
vlastne taká vec dobrá? Možno o tom ani neviete, ale Java Annotation
Processor je súčasťou bežnej praxe u enterprise
projektov. Je dosť možné, že túto technológiu využívate a ani o tom
neviete. Poďme sa spoločne ponoriť do tajov sveta
anotácií.
Motivačný príklad
V komerčnom svete sa používajú na komunikáciu medzi dvoma samostatnými systémami (najčastejšie) správy vo formáte XML. Každé XML možno generovať z jeho predpisu, tzv. XSD súboru. Z XSD súboru možno tiež vygenerovať Java triedy, ktoré budú obsahovať rovnaké atribúty, ako XML. Toto generovanie môže urobiť buď zodpovedajúcim Maven pluginom, alebo práve pomocou Java Annotation Processor.
Predpoklady
Než začnete čítať, je dobré sa uistiť, že rozumiete nižšie uvedené problematike:
Bez týchto znalostí sa budete kurzom prehrabávať len veľmi ťažko, preto si prípadne prvýkrát prejdite vyššie uvedené kurzy.
Java Anotácia
Anotácia by sa dala chápať ako sprievodné informácie k určitému elementu v kóde. Takýto element môže byť napríklad: balík, trieda, metóda, triedne premenná, parameter metódy, alebo iná anotácie.
To je síce pekná definícia, ale stále nám to nehovorí k čomu je dobré
elementy v kóde nejako dodatočne popisovať. Každý správny Java
programátor určite pozná anotáciu @Override
, ktorá sa
používa pri metódach tried, ktoré sú definované v jej predkovi, alebo v
rozhraní. Anotácií hovoríme, že metódu budeme prepisovať, resp.
implementovať.
Zamýšľali ste sa niekedy nad tým, čo by sa stalo, keby ste túto
anotáciu nepridali? Na prekvapenie mnohých nič závažné. Kód by išiel
stále preložiť, dokonca aj spustiť. Prečo ju teda vlastne píšeme?
Odpoveď je jednoduchá: kvôli lepšej čitateľnosti kódu. Anotácia
@Override
patrí do skupiny Information for the
compiler. To znamená, že táto anotácie nebude nijako obsiahnutá vo
výslednom kóde. V rovnakom duchu je v Jave v základe prítomná anotácia
@Deprecated
, slúžiaci na označenie zastaraných metód, ktoré
budú v novších verziách odobraté. Ďalej tu môžeme nájsť anotácie
@SuppressWarnings
pre potlačenie varovania a
@FunctionalInterface
pre označenie funkcionálního rozhranie (z
lekcie Úvod do
StreamAPI a lambda výrazov v Jave vieme, že sa jedná o zaručenie, že
rozhranie bude obsahovať len jednu abstraktné metódu).
Tieto anotácie majú spoločnú jednu vec: je možné ich spracovať
Java Annotation processor. Ak napríklad použijeme metódu
označenú anotácií @Deprecated
, dostaneme od kompilátora
vyhubováno, že používame zastarané API. Kód ale bude stále možné
preložiť a spustiť.
Vlastné anotácie
Keď sme si povedali, čo to vlastne anotácie je, poďme si ukázať, ako takú anotáciu vytvoriť. Syntax vyzerá nasledovne:
[@DoplnujiciAnotace]
[ModifikatorPristupu] @interface<NazevAnotace> {
DatovyTyp <nazevVlastnosti>() [vychoziHodnota];
}
Takáto definícia je síce pekná, ale len málokomu pochopiteľná. Všetko si preto vysvetlíme na príklade.
Príklad
Povedzme, že chceme anotáciu, ktorá označí triedu ako že reprezentuje tabuľku v databáze. Takáto anotácia by potom vyzerala asi takto:
public @interface Table { String name() default "Tabuľka"; }
Anotáciu deklarujeme teda ako rozhranie. V tom nehľadajte žiadny vyšší zmysel, niečo sa na ich špecifikáciu vybrať muselo, aby sa nemusela zbytočne definovať nová gramatika jazyka:) Ako ste si vyššie možno všimli, k anotácii možné priraďovať ďalšie anotácie. To sme zatiaľ u tej našej neurobili, poďme to napraviť.
Anotácie pre anotácie
Určite sa nenechajte zmiasť tým, že k anotáciám priraďujeme iné anotácie:) Je to logické, pretože ju potrebujeme definovať ešte niekoľko vecí a keďže je deklarovaná ako rozhranie, tak čím pridáme nejakú dodatočnú informáciu k rozhraniu ... no čím iným, než anotácií.
U anotácie spravidla dospecifikováváme 2 veci a je potrebné uvádzať vždy obe príslušné anotácie, aby sme si boli istí, že sa nepoužije nesprávna.
@Retention
Táto anotácia definuje v akej úrovni bude nami definovaná anotácie dostupná. K dispozícii sú 3 úrovne:
RetentionPolicy.SOURCE
- Naše anotácia bude dostupná len na úrovni zdrojového kódu. Kompiler ju bude ignorovať.RetentionPolicy.CLASS
- Naše anotácia pôjde použiť počas prekladu. Do bajtkódu sa ale nedostane.RetentionPolicy.RUNTIME
- Naše anotácia bude dostupná za behu programu.
@Target
Táto anotácia definuje u akého elemente pôjde naše anotácie použitý. Sú k dispozícii nasledujúce elementy:
ElementType.ANNOTATION_TYPE
- Naše anotácia bude použiteľná pre ďalšie anotácie.ElementType.CONSTRUCTOR
- Naše anotácia bude použiteľná na konštruktor.ElementType.FIELD
- Naše anotácia bude použiteľná na triedne premenné.ElementType.LOCAL_VARIABLE
- Naše anotácia bude použiteľná na premenné.ElementType.METHOD
- Naše anotácia bude použiteľná na metódy.ElementType.PACKAGE
- Naše anotácia bude použiteľná na balíčky.ElementType.PARAMETER
- Naše anotácia bude použiteľná na parametre metód.ElementType.TYPE
- Naše anotácia bude použiteľná na triedy.
Na účely nášho kurzu sa zameriame hlavne na také anotácie, ktoré budú
označené RetentionPolicy.SOURCE
a ElementType.TYPE
.
Kompletné ukážku vytvorenie vlastnej anotácie si ukážeme hneď
nabudúce.
Java Annotation Processor
Po divokom zoznámení s anotáciami sa v závere konečne dostávame k
hlavnej téme. Java Annotation Processor. Ten, ako sme si už
povedali, slúži na predspracovanie anotácií, ktoré sú
označené RetentionPolicy.SOURCE
, teda ktoré sa do
výslednej aplikácie nedostanú.
Zo začiatku budeme generovať výsledné Java súbory priamym písaním štruktúry v zdrojovom kóde. Na pokročilejšie veci si vezmeme na pomoc Apache Velocity.
V ďalšej lekcií, Annotation processor v Jave - Tvorba Maven projektu , si vytvoríme kostru projektu, na ktoré budeme s Java Annotation Processor ďalej pracovať.