Как работают пользовательские аннотации? - PullRequest
9 голосов
/ 10 октября 2011

Я все еще довольно новичок в программировании на Java, и я просматривал проект с открытым исходным кодом и наткнулся на это

public @TileNetworkData int progressPart = 0;   

Я уже видел использование @ раньше, но только для таких вещей, как @override перед участником.К моему удивлению, глядя на определение, оно привело меня к пользовательскому коду

import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface TileNetworkData {

    int staticSize () default -1; 

}

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

Занимаясь поиском в Google, я обнаружил, что это называется «Аннотации», но все, что с ним связано, ушло мне в голову.Буду признателен за любой пример, где будет использоваться нечто подобное.

Ответы [ 4 ]

5 голосов
/ 10 октября 2011

Аннотации используются в качестве «машиночитаемых метаданных» - они описывают поля, методы и классы, которые они помечают, таким образом, что компилятор и среда выполнения могут анализировать и, возможно, даже понимать. Если вы знакомы с .NET-атрибутами , вы обнаружите, что аннотации Java используются аналогично.

Например, аннотация TileNetworkData, определенная в вашем примере, сама украшена аннотацией Retention(RetentionPolicy.RUNTIME). Это говорит компилятору о встраивании аннотации TileNetworkData в байт-код для полей, которые он аннотирует. Эта же аннотация также сообщает среде выполнения Java, что при загрузке классов с полями, аннотированными TileNetworkData, она должна сохранять аннотацию TileNetworkData для отражения во время выполнения.

Теперь ваш код может отражать поля объекта, чтобы найти аннотации TileNetworkData и что-то делать с аннотированными полями:

// I haven't even compiled this code, and even if it works, it's still insane.
// (others who know annotations better should feel free to edit or replace)
public void copyTileNetworkDataToCache (Object data, Cache<?> cache) {
  for (Field f : data.getClass().getFields()) {
    if (f.isAnnotationPresent(TileNetworkData.class)) {
      cache.save(f.get(data));
    }
  }
}

Вы даже можете написать код, который учит Java-компилятор , как интерпретировать ваши аннотации во время компиляции , используя apt внешний интерфейс в JDK 5 и javac в JDK 6 и более поздних версиях. Чтобы создать еще один неудачный пример, доступ к сети плиток может занять так много времени, что вы захотите по возможности избегать использования данных из нее. Следовательно, вы можете захотеть составить список всех классов, включающих поля, аннотированные TileNetworkData, чтобы вы могли просмотреть их все и, возможно, переписать те, которые абсолютно не нужны для доступа к сети листов. Для этого вы можете написать процессор аннотаций, который распечатывает все подходящие классы, а затем указать apt на процессор при компиляции.

4 голосов
/ 10 октября 2011

Пример: демаркация транзакции:

public class TransactionalThing {
    @Transactional
    public void doSomePersistenceStuff() {
        Foo foo = loadAFoo();
        doSomeStuffWith(foo);
        foo.setProcessed(true);
    }
}

Был бы другой код, который ищет методы, аннотированные @Transactional, запускает транзакцию до вызова метода и фиксирует (или откатывает) транзакциюкогда это закончится.Вы также можете поместить в аннотацию информацию о таких вещах, как, например, правила отката:

@Transactional(rollbackFor = SomeException.class,
               noRollbackFor = SomeOtherException.class)

И снова, это зависит только от кода, который сканирует эти транзакции для считывания в этих атрибутах и ​​соответствующей обработки вещей.

2 голосов
/ 10 октября 2011

Аннотации используются для метаданных, для описания методов, классов и других типов объектов.

Вы можете использовать метаданные (описания данных) для ваших классов Java. Классическим примером является @ Устаревший , который помечает метод как «не подлежащий использованию в будущем».

Например, вы можете использовать их для добавления информации о конфигурации в класс Java. Если вы используете Hibernate (ORM), вы добавляете Annotations к классу, говоря, что этот класс должен быть заполнен информацией, содержащейся в таблице базы данных table_xxx, а информация столбца column_xxx должна храниться в том или ином поле в классе.

Код, который вы опубликовали, определяет аннотацию. Это позволит использовать эту аннотацию в другом месте вашего кода. В нем говорится, что аннотация будет доступна во время выполнения, @Retention(RetentionPolicy.RUNTIME), и что аннотация должна быть доступна как классу, который ее использует, так и любым подклассам этого класса.

Для получения дополнительной информации см. Ответы на Как и где аннотации используются в Java?

1 голос
/ 10 октября 2011

Метаданные могут быть запрошены через отражение. Таким образом, если где-то в коде есть универсальный void submitTileNetworkData(Object model), он может перебирать поля model и создавать двоичный дамп на основе аннотаций TileNetworkData.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...