Annotatieparameters tijdens runtime wijzigen

1. Overzicht

Annotaties , een vorm van metadata die u aan Java-code kunt toevoegen. Deze annotaties kan tijdens het compileren worden verwerkt en in klassebestanden worden ingesloten of kan tijdens runtime worden bewaard en geopend met Reflectie .

In dit artikel bespreken we hoe u kunt veranderen annotatie waarde tijdens runtime met Reflectie. We zullen annotaties op klasniveau gebruiken voor dit voorbeeld.

2. Annotatie

Java maakt het mogelijk om nieuwe annotaties gebruikmakend van bestaande. In de eenvoudigste vorm wordt een annotatie weergegeven als @ symbool gevolgd door annotatienaam:

@Override

Laten we onze eigen annotatie maken Greeter:

@Retention (RetentionPolicy.RUNTIME) public @interface Greeter {public String greet () default ""; }

Nu gaan we een Java-klasse maken Groeten die het klassenniveau gebruikt annotatie :

@Greeter (greet = "Good morning") openbare les Groeten {} 

Nu krijgen we toegang tot de annotatiewaarde met behulp van reflectie. Java-klasse Klasse biedt een methode getAnnotation om toegang te krijgen tot annotaties van een klas:

Greeter greetings = Greetings.class.getAnnotation (Greeter.class); System.out.println ("Hallo," + greetings.greet () + "!!");

3. Annotatie wijzigen

Java-klasse Klasse onderhoudt een kaart voor het beheren van annotaties - Annotatie class als sleutels en Annotatie object als waarde:

Kaart kaart;

We zullen deze kaart bijwerken om annotatie tijdens runtime te wijzigen. De aanpak om toegang te krijgen tot deze kaart verschilt in verschillende JDK-implementaties. We zullen het bespreken voor JDK7 en JDK8.

3.1.JDK 7 implementatie

Java-klasse Klasse heeft veld annotaties. Omdat dit een privéveld is, moeten we de toegankelijkheid van het veld instellen op waar. Java biedt methode getDeclaredField om toegang te krijgen tot elk veld met zijn naam:

Veldannotaties = Class.class.getDeclaredField (ANNOTATIES); annotations.setAccessible (true); 

Laten we nu toegang krijgen tot de annotatiekaart voor de les Greeter:

 Kaart map = annotations.get (targetClass);

Dit is nu de kaart die informatie bevat over alle annotaties en hun waardeobject. We willen veranderen Greeter annotatiewaarde die we kunnen bereiken door het annotatie-object van bij te werken Greeter klasse:

map.put (targetAnnotation, targetValue);

3.2.JDK 8-implementatie

Opslag van Java 8-implementaties annotaties informatie binnen een klas AnnotationData . We hebben toegang tot dit object met behulp van de annotationData methode. We zullen toegankelijkheid instellen voor het annotationData methode om waar aangezien het een privémethode is:

Method method = Class.class.getDeclaredMethod (ANNOTATION_METHOD, null); method.setAccessible (true);

Nu hebben we toegang annotaties veld. Omdat dit veld ook een privéveld is, zullen we toegankelijkheid instellen op waar:

Veldannotaties = annotationData.getClass (). GetDeclaredField (ANNOTATIES); annotations.setAccessible (true);

Dit veld heeft een annotatiecachekaart waarin de annotatieklasse en het waardeobject worden opgeslagen. Laten we dat veranderen:

Kaart map = annotations.get (annotationData); map.put (targetAnnotation, targetValue);

4. Toepassing

Laten we dit voorbeeld nemen:

Greeter greetings = Greetings.class.getAnnotation (Greeter.class); System.err.println ("Hallo," + greetings.greet () + "!!");

Dit is een begroeting met 'Goedemorgen', want dat is de waarde die we aan de annotatie hebben gegeven.

Nu gaan we nog een object maken van Greeter typ met waarde als 'Goedenavond':

Greeter targetValue = nieuwe DynamicGreeter ("Goedenavond"); 

Laten we de annotatiekaart bijwerken met de nieuwe waarde:

alterAnnotationValueJDK8 (Greetings.class, Greeter.class, targetValue);

Laten we de begroetingswaarde opnieuw controleren:

greetings = Greetings.class.getAnnotation (Greeter.class); System.err.println ("Hallo," + greetings.greet () + "!!");

Het zal begroeten als "Goedenavond".

5. Conclusie

Java-implementaties gebruiken twee gegevensvelden om annotatiegegevens op te slaan: annotaties, verklaarde annotaties. Het verschil tussen deze twee: sla eerst annotaties van bovenliggende klassen ook op en later slaat men alleen op voor de huidige klasse.

Zoals de implementatie van getAnnotation verschilt in JDK 7 en JDK 8, gebruiken we hier annotaties veldkaart voor eenvoud.

En, zoals altijd, is de broncode van de implementatie beschikbaar op Github.