Подтвердить что ты не робот

Как аннотации работают внутри

Может кто-нибудь объяснить мне, как аннотация работает внутри java?

Я знаю, что мы можем создать пользовательскую аннотацию, используя библиотеку java.lang.annotation в java. Но все же я не понимаю, как он работает внутри, например, @Override аннотации.

Я очень благодарен, если кто-нибудь объяснит это подробно.

4b9b3361

Ответ 1

Первое основное различие между типами аннотаций заключается в том, используются ли они во время компиляции, а затем отбрасываются (например, @Override) или помещаются в скомпилированный файл класса и доступны во время выполнения (например, Spring @Component). Это определяется @Сохранение политики аннотации. Если вы пишете собственную аннотацию, вам нужно будет решить, полезно ли аннотирование во время выполнения (для автоконфигурации, возможно) или только во время компиляции (для проверки или генерации кода).

При компиляции кода с аннотациями компилятор видит аннотацию так же, как видит другие модификаторы исходных элементов, такие как модификаторы доступа (public/private) или final. Когда он сталкивается с аннотацией, он запускает обработчик аннотации, который похож на класс подключаемого модуля, который говорит, что он интересуется конкретной аннотацией. Обработчик аннотации обычно использует API Reflection для проверки скомпилированных элементов и может просто запускать проверки на них, изменять их или генерировать новый код для компиляции. @Override является примером первого; он использует API Reflection, чтобы убедиться, что он может найти соответствие для сигнатуры метода в одном из суперклассов и использует Messager, чтобы вызвать ошибку компиляции, если он не может.

При написании обработчиков аннотаций имеется ряд обучающих программ; здесь полезный. Просмотрите методы интерфейса Processor о том, как компилятор вызывает обработчик аннотации; основная операция выполняется в методе process, который вызывается каждый раз, когда компилятор видит элемент с соответствующей аннотацией.

Ответ 2

Кроме того, что другие предложили, я рекомендую вам написать индивидуальную аннотацию и ее процессор с нуля, чтобы увидеть, как работает аннотация.

В моем собственном, например, я написал аннотацию, чтобы проверить, перегружены ли методы во время компиляции.

Во-первых, создайте аннотацию с именем Overload. Эта аннотация применяется к методу, поэтому я аннотирую его с помощью @Target(value=ElementType.METHOD)

package gearon.customAnnotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target(value=ElementType.METHOD)
public @interface Overload {

}

Затем создайте соответствующий процессор для обработки элементов, аннотированных определенной аннотацией. Для метода, аннотированного @Overload, его подпись должна появляться более одного раза. Или ошибка напечатана.

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;
    }
}

После упаковки аннотации и ее процесса в файл jar создайте класс с @Overload и используйте javac.exe для его компиляции.

import gearon.customAnnotation.Overload;

public class OverloadTest {
    @Overload
    public static void foo(){
    }

    @Overload
    public static void foo(String s){

    }

    @Overload
    public static void nonOverloadedMethod(){

    }
} 

Так как nonOverloadedMethod() на самом деле не перегружен, мы получим результат, как показано ниже:

введите описание изображения здесь

Ответ 3

Здесь @Override: http://www.docjar.com/html/api/java/lang/Override.java.html.

Там нет ничего особенного, что отличает его от аннотации, которую вы могли бы написать сами. Интересные биты находятся в потребителях аннотаций. Для аннотации, такой как @Override, это было бы в самом компиляторе Java или в инструменте анализа статического кода или в вашей среде IDE.

Ответ 4

Следуйте за этой ссылкой . Это поможет вам ответить на ваши вопросы. Если мы сосредоточились на аннотации в Java, аннотации были введены в Java 5 и не были специфическими для Spring. В общем, аннотации позволяют добавлять метаданные к классу, методу или переменной. Аннотацию можно интерпретировать компилятором (например, аннотацией @Override) или каркасом, например Spring (например, аннотация @Component).

Кроме того, я добавляю больше ссылок.

Ответ 5

В основном аннотации - это только маркеры, которые читаются компилятором или приложением. В зависимости от их политики хранения они доступны только во время компиляции или могут быть прочитаны во время выполнения с использованием отражения.

Многие фреймворки используют сохранение во время выполнения, то есть они рефлексивно проверяют, присутствуют ли какие-либо аннотации в классе, методе, поле и т.д. и что-то делают, если аннотация присутствует (или нет). Кроме того, члены аннотаций могут использоваться для передачи дополнительной информации.