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

Java

что такое аннотации

Аннотации можно описать одним словом, и это метаданные, тип данных, который описывает данные. Следовательно, можно сказать, что аннотации — это метаданные исходного кода. Например, следующий код:

@Override
public String toString() {
return "This is String Representation of current object.";
}

Приведенный выше код, метод rewrite toString() и используемые аннотации @Override.

На самом деле, @Override сообщает компилятору, что этот метод является методом переопределения (метаданные, описывающие метод), и если метод не существует в родительском классе, компилятор сообщит об ошибке, что метод не переопределяет метод в родительском классе. родительский класс. Если вы случайно допустили ошибку, например, toString() записывается как toString(){double r}, а аннотация @Override не используется, программа все равно скомпилируется и запустится, но результат выполнения будет сильно отличаться от ожидаемого .

Аннотация — это специальный модификатор, применяемый к объявлениям классов, методов, параметров, переменных, конструкторов и пакетов. Это инструмент, выбранный стандартом JSR-175 для описания метаданных. Используйте аннотации, чтобы облегчить чтение программ.

Зачем вводить аннотации

До использования аннотации (и даже после нее) XML широко использовался для описания метаданных. Каким-то образом некоторые разработчики и архитекторы приложений обнаружили, что поддержка XML становится все хуже и хуже. Они хотят использовать то, что тесно связано с кодом, а не описание кода, которое слабо связано (а в некоторых случаях полностью отделено) от кода, например XML. Если вы погуглите «XML против аннотаций», вы увидите много споров по этому вопросу. Самое интересное, что XML-конфигурация фактически представлена ​​раздельным кодом и конфигурацией. Две вышеприведенные точки зрения могут вас смутить, кажется, что они образуют некий цикл, но у каждой есть свои плюсы и минусы. Ниже мы используем пример, чтобы понять разницу между ними.

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

Еще одним важным фактором является то, что аннотация определяет стандартный способ описания метаданных. До этого разработчики обычно определяли метаданные по-своему. Например, используйте интерфейсы разметки, аннотации, переходные ключевые слова и т. д. Каждый программист определяет метаданные по-своему, а не стандартно, как Annotation.

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

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

Написать аннотацию очень просто, а саму аннотацию можно назвать классом. Определение аннотации можно сравнить с определением интерфейса. Например, стандартная аннотация @Override:

package java.lang;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

Как видите, аннотация @Override ничего не делает, так как же она проверяет наличие функции с таким же именем в родительском классе? Определение аннотации @Override представляет собой только метаданные и не содержит бизнес-логики, а пользователь аннотации реализует бизнес-логику.

Для аннотации @Override ее пользователем является виртуальная машина JVM, которая работает на уровне байт-кода и проверяется на этапе компиляции Механизм обработки — это в основном внутренняя обработка JVM.

Другой пример — Spring.@ServiceAnnotation, Spring сканирует каждый класс при запуске контейнера IOC и выполняет обработку bean-компонента для всех классов, отмеченных @Component и его поданнотациями, такими как @Service.

Создание пользовательских аннотаций

Версия JDK5.0 предоставляет четыре мета-аннотации в java.lang.annotation, которые специально аннотируют другие аннотации:

  • @Documented — добавлять ли аннотацию в java-документ.

  • @Retention — определяет жизненный цикл аннотации.

  • @Target — где используется аннотация

  • @Inherited — разрешать ли подклассам наследовать эту аннотацию

@RetentionАннотация определяет жизненный цикл аннотации, на каком этапе она отбрасывается,

  • RetentionPolicy.SOURCE — отбрасывается во время компиляции. Эти аннотации больше не имеют никакого значения после компиляции, поэтому они не записываются в байт-код. @Override, @SuppressWarnings относятся к этому типу аннотаций.

  • RetentionPolicy.CLASS — отбрасывается при загрузке класса, полезен при обработке файла байт-кода. Аннотации используют этот метод по умолчанию.

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

@Target– Указывает, где используется аннотация. Эта аннотация может быть размещена где угодно, если это не указано явно. Аннотации атрибутов совместимы.

  • ElementType.TYPE: используется для описания объявлений класса, интерфейса или перечисления.

  • ElementType.FIELD: используется для описания переменных экземпляра.

  • ElementType.METHOD

  • ElementType.PARAMETER

  • ElementType.CONSTRUCTOR

  • ElementType.LOCAL_VARIABLE

  • ElementType.ANNOTATION_TYPE другая аннотация

  • ElementType.PACKAGE используется для записи информации о пакете java-файлов.

Итак, как определяется внутренняя часть аннотации? Аннотации поддерживают только примитивные типы, типы String и перечисления. Все свойства в аннотациях определяются как методы и позволяют указывать значения по умолчанию.

определить@AuthCheckАннотация, действующая на метод контроллера SpringMVC.

package com.liuning.sys.auth;

import static java.lang.annotation.ElementType.METHOD;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Target(METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthCheck {
	String value() default "";
}

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

Перехватчики веснойHandlerInterceptorБизнес-логика аннотации @AuthCheck реализована в механизме отражения.

@Override
public boolean preHandle(HttpServletRequest request, 
                         HttpServletResponse response, 
                         Object handler) throws Exception {
	HandlerMethod hm = (HandlerMethod) handler;
	AuthCheck ac = hm.getMethodAnnotation(AuthCheck.class);
	if (ac != null) {
		if (ac.value() == "Login") {
			//进行业务逻辑操作
		}
	}
	return true;
}

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

@PostMapping("/list")
@AuthCheck(value = "Login")
public List<User> getUserList(@RequestBody @Valid User user) {
    
    return userService.getUserList(user);
}