Czy ktoś może mi wyjaśnić, jak adnotacje działają wewnętrznie w Javie?
Wiem, jak możemy tworzyć własne adnotacje za pomocą biblioteki java.lang.annotation w java. Ale nadal nie rozumiem, jak to działa wewnętrznie, na przykład adnotacja @Override.
Byłbym bardzo wdzięczny, gdyby ktoś mógł to szczegółowo wyjaśnić.
java
annotations
Chirag Dasani
źródło
źródło
Odpowiedzi:
Pierwszą główną różnicą między rodzajami adnotacji jest to, czy są one używane w czasie kompilacji, a następnie odrzucane (jak
@Override
), czy też umieszczane w skompilowanym pliku klasy i dostępne w czasie wykonywania (jak Spring@Component
). Jest to określone przez zasadę @Retention adnotacji. Jeśli piszesz własną adnotację, musisz zdecydować, czy adnotacja jest pomocna w czasie wykonywania (na przykład do autokonfiguracji), czy tylko w czasie kompilacji (do sprawdzania lub generowania kodu).Podczas kompilowania kodu z adnotacjami kompilator widzi adnotację tak samo, jak widzi inne modyfikatory w elementach źródłowych, takie jak modyfikatory dostępu (
public
/private
) lubfinal
. Kiedy napotka adnotację, uruchamia procesor adnotacji, który jest jak klasa wtyczki, która mówi, że interesuje go określona adnotacja. Procesor adnotacji na ogół używa interfejsu API Reflection do sprawdzania kompilowanych elementów i może po prostu przeprowadzać testy, modyfikować je lub generować nowy kod do skompilowania.@Override
jest przykładem pierwszego; używa interfejsu API Reflection, aby upewnić się, że może znaleźć dopasowanie do sygnatury metody w jednej z nadklas, aMessager
jeśli nie, używa do spowodowania błędu kompilacji.Dostępnych jest wiele samouczków na temat pisania procesorów adnotacji; tutaj jest przydatny . Przejrzyj metod na tym
Processor
interfejsie dla jak kompilator wywołuje procesor adnotacji; główna operacja odbywa się wprocess
metodzie, która jest wywoływana za każdym razem, gdy kompilator widzi element, który ma pasującą adnotację.źródło
Oprócz tego, co sugerowali inni, radzę napisać od podstaw dostosowaną adnotację i jej procesor, aby zobaczyć, jak działa adnotacja.
Na przykład we własnym napisałem adnotację, aby sprawdzić, czy metody nie są przeciążone w czasie kompilacji.
Najpierw utwórz adnotację o nazwie
Overload
. Ta adnotacja jest stosowana do metody, więc dodaję do niej adnotację@Target(value=ElementType.METHOD)
package gearon.customAnnotation; import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target(value=ElementType.METHOD) public @interface Overload { }
Następnie utwórz odpowiedni procesor do obsługi elementów opisanych za pomocą zdefiniowanej adnotacji. W przypadku metody z adnotacją przez
@Overload
jej podpis musi pojawić się więcej niż jeden raz. Lub błąd zostanie wydrukowany.package gearon.customAnnotation; import java.util.HashMap; import java.util.Map.Entry; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic.Kind; @SupportedAnnotationTypes("gearon.customAnnotation.Overload") public class OverloadProcessor extends AbstractProcessor{ @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { // TODO Auto-generated method stub HashMap<String, Integer> map = new HashMap<String, Integer>(); for(Element element : roundEnv.getElementsAnnotatedWith(Overload.class)){ String signature = element.getSimpleName().toString(); int count = map.containsKey(signature) ? map.get(signature) : 0; map.put(signature, ++count); } for(Entry<String, Integer> entry: map.entrySet()){ if(entry.getValue() == 1){ processingEnv.getMessager().printMessage(Kind.ERROR, "The method which signature is " + entry.getKey() + " has not been overloaded"); } } return true; } }
Po spakowaniu adnotacji i jej przetworzeniu do pliku jar, utwórz klasę
@Overload
i użyj javac.exe do jej skompilowania.import gearon.customAnnotation.Overload; public class OverloadTest { @Overload public static void foo(){ } @Overload public static void foo(String s){ } @Overload public static void nonOverloadedMethod(){ } }
Ponieważ w
nonOverloadedMethod()
rzeczywistości nie został przeciążony, otrzymamy dane wyjściowe jak poniżej:źródło
OverloadProcessor::process
dlaczego tak jestentry.getValue() == 1
? Nie trzeba dodawać adnotacji w klasie / interfejsie nadrzędnym, więcroundEnv.getElementsAnnotatedWith(Overload.class)
nie otrzymamy klasy / interfejsu nadrzędnego, prawda?Tutaj
@Override
: http://www.docjar.com/html/api/java/lang/Override.java.html .Nie ma w tym nic specjalnego, co odróżnia je od adnotacji, którą możesz napisać samodzielnie. Interesujące fragmenty są w konsumentach adnotacji. W przypadku adnotacji, takich jak
@Override
, byłoby to w samym kompilatorze języka Java, narzędziu do analizy kodu statycznego lub w środowisku IDE.źródło
@Override
(lub innych standardowych adnotacji).Zasadniczo adnotacje to tylko znaczniki odczytywane przez kompilator lub aplikację. W zależności od ich zasad przechowywania są one dostępne tylko w czasie kompilacji lub można je odczytać w czasie wykonywania przy użyciu odbicia.
Wiele frameworków używa retencji środowiska uruchomieniowego, tj. W sposób refleksyjny sprawdzają, czy w klasie, metodzie, polu itp. Istnieją adnotacje, i robią coś, jeśli adnotacja jest obecna (lub nie). Ponadto członkowie adnotacji mogą służyć do przekazywania dalszych informacji.
źródło
Kliknij ten link . Zapewni to dokładną odpowiedź na Twój problem. Jeśli skupiliśmy się na adnotacjach w programie
Java
, adnotacje zostały wprowadzone w Javie 5 i nie są specyficzne dla Springa. Ogólnie rzecz biorąc, adnotacje umożliwiają dodawanie metadanych do klasy, metody lub zmiennej. Adnotację można zinterpretować przez kompilator (na przykład adnotację @Override) lub strukturę, taką jak spring (na przykład adnotacja @Component).Dodatkowo dodaję więcej referencji.
źródło
Nawet ja szukałem odpowiedzi na to samo pytanie. poniższy link zapewnia skonsolidowane dobre informacje, aby uzyskać dostęp do wnętrza adnotacji. https://dzone.com/articles/how-annotations-work-java Mam nadzieję, że to pomoże!
źródło