Поддержка обработчиков аннотаций в IDE NetBeans (часть II) Использование пользовательских обработчиков аннотаций в IDE

Составитель:, автор и редактор: Ирина Филиппова (Irina Filippova)

Содержимое на этой странице применимо к IDE NetBeans 6.9, 7.0 и 7.1

В этом разделе учебного курса описываются способы добавления собственного обработчика особых аннотаций в проект в среде IDE. Написание обработчика не входит в круг задач данного учебного курса. Здесь описывается добавление его к проекту IDE NetBeans.

Образец приложения, используемый в этом приложении, был создан Джесси Глик (Jesse Glick) и опубликован как Часто задаваемые вопросы по вводу для предыдущих выпусков IDE.

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

Для работы с этим учебным курсом требуются программное обеспечение и ресурсы, перечисленные ниже.

Программное обеспечение или материал Требуемая версия
IDE NetBeans 7.1, 7.2, 7.3
Комплект для разработчика на языке Java (JDK) версия 6

Примечания:

  • В IDE NetBeans выпуске 6.9 была добавлена поддержка нестандартных обработчиков аннотаций. Этот учебный курс не подходит для использования с предыдущими версиями среды IDE.

Определение аннотации и создание обработчика аннотаций

В этом упражнении мы создадим проект библиотеки классов.

  1. Выберите File ("Файл") > New Project ("Создать проект") и выберите тип проекта Java Class Library ("Библиотека классов Java") в категории Java. Нажмите кнопку "Далее".
  2. Введите AnnProcessor в поле Project Name ("Имя проекта") и укажите местоположение для проекта. Нажмите кнопку "Завершить".

    При нажатии кнопки "Готово" среда IDE создаст проект библиотеки классов, который появится в окне Projects ("Проекты").

  3. Щелкните правой кнопкой мыши узел проекта AnnProcessor в окне Projects ("Проекты") и выберите Properties ("Свойства").
  4. В категории Sources ("Источники") подтвердите, что для JDK 6 указан формат исходного кода/двоичный.
  5. Выберите вкладку Libraries ("Библиотеки") и подтвердите, что платформой Java является JDK 6. Нажмите кнопку "ОК", чтобы закрыть окно Project Properties ("Свойства проекта").

В этом упражнении мы создадим несколько пакетов Java и по одному классу Java в каждом из пакетов.

  1. Создайте пакет Java с именем ann щелкнув правой кнопкой мыши узел 'Исходные пакеты' в проекте AnnProcessor и выбрав 'Создать' > 'Пакет Java'. Введите ann в поле Package Name ("Имя пакета") и нажмите кнопку Finish ("Готово").
  2. Повторите предыдущее действие и создайте пакет Java под названием proc.

    После создания двух пакетов Java структура проекта должна быть подобной изображенной ниже.

    снимок окна 'Проекты', в котором отображаются пакеты Java
  3. Щелкните правой кнопкой мыши пакет Java ann и выберите New ("Создать") > Java class ("Класс Java").
  4. Введите Handleable в поле Class Name ("Имя класса"). Нажмите кнопку "Завершить".
  5. Измените файл Handleable.java, добавив приведенный ниже код. Сохраните файл.
    package ann;
    
    public @interface Handleable {
    
    }

    Так объявляются аннотации -- совершенно аналогично объявлению интерфейса. Различием является то, что ключевому слову interface должен предшествовать знак @. Эта аннотация именуется Handleable (обрабатываемой).

    Дополнительные сведения. В объявлениях аннотаций можно указать дополнительные параметры, например, типы элементов, к которым можно добавить аннотации, например, классы или методы. Для этого добавляется @Target(value = {ElementType.TYPE}) для классов и @Target(value = {ElementType.METHOD}). Таким образом, объявление аннотаций становится автоматическим с помощью мета-аннотаций.

    Теперь необходимо добавить к обработчику аннотаций код для обработки аннотации Handleable.

  6. Щелкните правой кнопкой мыши пакет Java proc и выберите New ("Создать") > Java class ("Класс Java").
  7. Введите HandleableProcessor в поле Class Name ("Имя класса"). Нажмите кнопку "Завершить".
  8. Измените класс HandleableProcessor.java, добавив нижеприведенный код. Сохраните изменения.
    package proc;
    
    import ann.Handleable;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.io.Writer;
    import java.util.Set;
    import javax.annotation.processing.AbstractProcessor;
    import javax.annotation.processing.RoundEnvironment;
    import javax.annotation.processing.SupportedAnnotationTypes;
    import javax.annotation.processing.SupportedSourceVersion;
    import javax.lang.model.SourceVersion;
    import javax.lang.model.element.Element;
    import javax.lang.model.element.ElementKind;
    import javax.lang.model.element.TypeElement;
    import javax.lang.model.type.TypeMirror;
    import javax.tools.Diagnostic;
    import javax.tools.JavaFileObject;
    
    @SupportedAnnotationTypes("ann.Handleable")
    @SupportedSourceVersion(SourceVersion.RELEASE_6)
    public class HandleableProcessor extends AbstractProcessor {
    
        /** public for ServiceLoader */
        public HandleableProcessor() {
        }
    
        public boolean process(Set annotations,
                RoundEnvironment roundEnv) {
            for (Element e : roundEnv.getElementsAnnotatedWith(Handleable.class)) {
                if (e.getKind() != ElementKind.FIELD) {
                    processingEnv.getMessager().printMessage(
                            Diagnostic.Kind.WARNING,
                            "Not a field", e);
                    continue;
                }
                String name = capitalize(e.getSimpleName().toString());
                TypeElement clazz = (TypeElement) e.getEnclosingElement();
                try {
                    JavaFileObject f = processingEnv.getFiler().
                            createSourceFile(clazz.getQualifiedName() + "Extras");
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,
                            "Creating " + f.toUri());
                    Writer w = f.openWriter();
                    try {
                        PrintWriter pw = new PrintWriter(w);
                        pw.println("package "
                                + clazz.getEnclosingElement().getSimpleName() + ";");
                        pw.println("public abstract class "
                                + clazz.getSimpleName() + "Extras {");
                        pw.println("    protected " + clazz.getSimpleName()
                                + "Extras() {}");
                        TypeMirror type = e.asType();
                        pw.println("    /** Handle something. */");
                        pw.println("    protected final void handle" + name
                                + "(" + type + " value) {");
                        pw.println("        System.out.println(value);");
                        pw.println("    }");
                        pw.println("}");
                        pw.flush();
                    } finally {
                        w.close();
                    }
                } catch (IOException x) {
                    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
                            x.toString());
                }
            }
            return true;
        }
    
        private static String capitalize(String name) {
            char[] c = name.toCharArray();
            c[0] = Character.toUpperCase(c[0]);
            return new String(c);
        }
    }

    Давайте рассмотрим внимательнее основные части кода, образующие обработчик аннотаций (обратите внимание, что для удобства рассмотрения код приведен здесь лишь частично).

    Сперва следует указать типы аннотаций, поддерживаемые обработчиком аннотаций (используя @SupportedAnnotationTypes) и поддерживаемую версию исходных файлов (используя @SupportedSourceVersion). В данном случае версией является JDK 6:

    @SupportedAnnotationTypes("ann.Handleable")
    @SupportedSourceVersion(SourceVersion.RELEASE_6)

    Затем следует объявить общедоступный класс для обработчика, расширяющий классAbstractProcessor из пакета javax.annotation.processing. AbstractProcessor является стандартным надклассом для обработчиков конкретных аннотаций и содержит необходимые методы для обработки аннотаций.

    public class HandleableProcessor extends AbstractProcessor {
    ...
    }

    Теперь необходимо предоставить общедоступный конструктор для данного класса.

    public class HandleableProcessor extends AbstractProcessor {
        public HandleableProcessor() {
        }
    ...
    
    }

    Затем следует вызвать метод process() родительского класса AbstractProcessor. Посредством этого метода предоставляются аннотации, доступные для обработки. Кроме того, этот метод содержит данные о цикле обработки.

    public class HandleableProcessor extends AbstractProcessor {
       ...
         public boolean process(Set annotations,
                RoundEnvironment roundEnv) {
         ...
         }
    
    }

    Логика обработчика аннотаций содержится внутри метода process() класса AbstractProcessor. Обратите внимание, что при помощи класса AbstractProcessor также можно получить доступ к интерфейсу ProcessingEnvironment, позволяющему обработчикам аннотаций использовать несколько полезных функций, например средство для работы с файловой системой (обработчик файловой системы, позволяющий обработчикам аннотаций создавать файлы) и средство вывода сообщений (способ предупреждения об ошибках обработчиков аннотаций).

    public class HandleableProcessor extends AbstractProcessor {
       ...
         public boolean process(Set annotations,
                RoundEnvironment roundEnv) {
    //For each element annotated with the Handleable annotation for (Element e : roundEnv.getElementsAnnotatedWith(Handleable.class)) {
    //Check if the type of the annotated element is not a field. If yes, return a warning.
    if (e.getKind() != ElementKind.FIELD) {
    processingEnv.getMessager().printMessage(
    Diagnostic.Kind.WARNING,
    "Not a field", e);
    continue;
    }
    //Define the following variables: name and clazz.
    String name = capitalize(e.getSimpleName().toString());
    TypeElement clazz = (TypeElement) e.getEnclosingElement();
    //Generate a source file with a specified class name. try {
    JavaFileObject f = processingEnv.getFiler().
    createSourceFile(clazz.getQualifiedName() + "Extras");
    processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,
    "Creating " + f.toUri());
    Writer w = f.openWriter();
    //Add the content to the newly generated file. try {
    PrintWriter pw = new PrintWriter(w);
    pw.println("package "
    + clazz.getEnclosingElement().getSimpleName() + ";");
    pw.println("public abstract class "
    + clazz.getSimpleName() + "Extras {");
    pw.println(" protected " + clazz.getSimpleName()
    + "Extras() {}");
    TypeMirror type = e.asType();
    pw.println(" /** Handle something. */");
    pw.println(" protected final void handle" + name
    + "(" + type + " value) {");
    pw.println(" System.out.println(value);");
    pw.println(" }");
    pw.println("}");
    pw.flush();
    } finally {
    w.close();
    }
    } catch (IOException x) {
    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
    x.toString());
    }
    }

    return true; } ... }

    В последнем блоке этого кода объявляется метод capitalize, используемый для написания имени аннотированного элемента с заглавной буквы.

    public class HandleableProcessor extends AbstractProcessor {
       ...
    
      private static String capitalize(String name) {
    char[] c = name.toCharArray();
    c[0] = Character.toUpperCase(c[0]);
    return new String(c);
    }
    }
  9. Создайте проект, щелкнув правой кнопкой мыши проект AnnProcessor и выбрав 'Сборка'.

Работа с обработчиком аннотаций в среде IDE

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

  1. Выберите File ("Файл") > New Project ("Создать проект") и выберите тип проекта Java Application ("Приложение Java") в категории Java. Нажмите кнопку "Далее".
  2. На странице Name and Location ("Имя и местоположение") введите Demo в поле Project Name ("Имя проекта") и укажите местоположение проекта.
  3. Введите demo.Main в поле Create Main Class ("Создать главный класс"). Нажмите кнопку "Завершить".
    моментальный снимок мастера создания проектов
  4. Откройте окно свойств проекта и убедитесь, что JDK 6 выбран как двоичный формат/формат исходного кода на панели Sources ("Исходные коды"), а также что JDK 6 установлен как платформа Java на панели Libraries ("Библиотеки").
  5. Измените класс Main.java, добавив приведенный ниже код. Сохраните изменения.
    package demo;
    
    import ann.Handleable;
    
    public class Main extends MainExtras {
    
        @Handleable
        private String stuff;
    
        public static void main(String[] args) {
            new Main().handleStuff("hello");
        }
    }

    Данный код содержит следующие элементы:

    • оператор импорта для обработчика особых аннотаций ann.Handleable;
    • общедоступный класс Main, расширяющий класс MainExtras (MainExtras должен быть создан обработчиком аннотаций во время компиляции);
    • закрытое поле под названием stuff, с аннотацией @Handleable;
    • метод main, вызывающий метод handleStuff, который объявляется в автоматически создаваемом классе MainExtras.

      В этом простом примере метод handleStuff только распечатывает текущее значение. Назначение метода можно изменить.

    После сохранения кода Main.java можно увидеть, что среда IDE сообщает о ряде ошибок компиляции. Это происходит, поскольку обработчик аннотаций еще не добавлен в проект.

  6. Щелкните правой кнопкой мыши узел проекта Demo в окне Projects ("Проекты"), выберите Properties ("Свойства"), затем выберите категорию Libraries ("Библиотеки") в окне свойств.
  7. На вкладке Compile ("Компиляция") щелкните Add Project ("Добавить проект") и найдите проект AnnProcessor.
    снимок вкладки 'Компилировать' в категории 'Библиотеки' окна свойств проекта

    Вкладка "Компиляция" соответствует параметру -classpath компилятора Java. Поскольку обработчик аннотаций является единым файлом JAR, который содержит как определение аннотаций, так и обработчик аннотаций, его следует добавить к пути классов для проекта, которым является вкладка Compile ("Компиляция").

  8. Выберите категорию Compiling ("Компиляция") в окне Properties ("Свойства") и установите флажки Enable Annotation Processing ("Включить обработку аннотаций") и Enable Annotation Processing in Editor ("Включить обработку аннотаций в редакторе").
  9. Укажите, какой обработчик аннотаций должен быть запущен, нажав кнопку Add ("Добавить") рядом с текстовой областью обработчиков аннотаций и введя proc.HandleableProcessor в поле FQN ("Полностью определенное имя") обработчика аннотаций.
    снимок диалогового окна 'FQN обработчика аннотаций'

    Категория Compiling ("Компиляция") в окне Properties ("Свойства") должна выглядеть, как на приведенном ниже изображении.

    снимок категории "Компиляция" в окне "Свойства проекта".
  10. Нажмите кнопку OK в окне Properties ("Свойства").

    Примечание. В файле Main.java все еще могут отображаться ошибки компиляции. Это происходит, поскольку в среде IDE еще не определено местоположение файла MainExtras.java, в котором объявляется метод handleStuff. После первого создания проекта Demo будет создан файл MainExtras.java. Если для проекта включено режим Compile On Save ("Компилировать при сохранении"), среда IDE компилирует проект при сохранении Main.java.

  11. Щелкните правой кнопкой мыши проект Demo и выберите Build ("Сборка").

    Если после сборки проекта взглянуть на него в окне Projects ("Проекты"), то можно будет увидеть новый узел Generated Sources с файлом demo/MainExtras.java.

    снимок окна 'Проекты' с созданными источниками

    При просмотре содержимого созданного файла MainExtras.java можно увидеть, что обработчик аннотаций создал класс MainExtras с методом handleStuff. Метод handleStuff и является методом, вызываемым из аннотированного файла Main.java.

    package demo;
    public abstract class MainExtras {
        protected MainExtras() {}
        /** Handle something. */
        protected final void handleStuff(java.lang.String value) {
            System.out.println(value);
        }
    }
  12. Щелкните правой кнопкой мыши проект Demo и выберите Run ("Запустить").

    При щелчке Run ("Запустить") в окне вывода можно будет увидеть следующее. Выполняется компиляция проекта Demo, и на экран выводится сообщение.

    снимок окна 'Проекты' с созданными источниками

Дополнительные сведения

Ознакомьтесь со следующими ресурсами для получения дополнительных сведений об аннотациях в приложениях Java:

get support for the NetBeans

Support


By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2013, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo