Это штуки, которые мы можем встретить в коде. Они начинаются из символа @.
Многие Java API требуют написания большого количества рутинного кода, другие Java API требуют присутсвия рядом с классами "сайд-файлов".
Так вот эти штуки помогают компилятору явы (javac) или утилите apt(Annotation Processing Tool), генерить этот код автоматически вместо того, чтобы его писать руками.
Вот примеры применения:
1) Написание JAX-RPC web-сервисов требует, чтобы были определены и интерфейсы и их реализации. Это может сделать платформа автоматически если возле методов, которые будут вызываться удаленно, ставить аннотации.
2) JavaBeans должны сопровождаться классами BeanInfo. А EJB дескриптором развертования. Продуктивнее и более безопасно в плане ошибок, чтобы эти файлы генерировались на основании аннотаций в коде автоматически.
Есть и много других полезных старых анотаций:
Анотации очень похожы на javadoc, они даже дополняют их, но между ними есть четкое отличие. Вторые используются только для автоматической генерации документаций. А первые влият на работу программы (хотя не через саму семантику программы, а влияя на интрументарий jdk и на библиотеки).
Анотации мы можем счиатать из исходников, откомпилированных классов и даже из обьектов на этапе выполнения приложения.
Чтобы создать собственную аннотацию, мы должны ее описать, и сделать для нее собственный процессор, а также указать этот процессор в файле архива
Для примера собственной аннотации придумаем себе задачу и решим ее. Этот пример взят из http://www.javaspecialists.eu/archive/Issue167.html.
Допустим нам нужно в определенных классах обеспечить, чтобы они имели полюбому публичный контсруктор без аргументом, при этом выявить такие классы мы должны не тестируя откомпилированное приложение, а на этапе компиляции(по-этому вопрос с исключениями сразу отпадает).
Первое опишем аннотацию:
Как видим в описании аннотации уже используются готовые аннотации) Разберем их:
@Inherited - означает, что наследники класса, к которому применена аннотация, наследывают и аннотацию тоже.
@Documented - означает, что в документацию javadoc будет заносить эту аннотацию.
@Retention(RetentionPolicy.SOURCE) - означает, что аннотация будет доступна только на этапе компиляции(или запуска apt), в момент работы приложения аннотация не доступна.
@Target(ElementType.TYP) - означает, что эта аннотация применима только к классам.
Теперь пришло время создать файл процессора для нашей аннотации:
Запакуем наши созданные файлы для аннотации в архивчик apttools.jar, при этом не забудем в нем создать файл
А теперь создадим код для тестирования нашей аннотации:
И попрообуем его откомпилировать с учетом наших аннотаций:
Многие Java API требуют написания большого количества рутинного кода, другие Java API требуют присутсвия рядом с классами "сайд-файлов".
Так вот эти штуки помогают компилятору явы (javac) или утилите apt(Annotation Processing Tool), генерить этот код автоматически вместо того, чтобы его писать руками.
Вот примеры применения:
1) Написание JAX-RPC web-сервисов требует, чтобы были определены и интерфейсы и их реализации. Это может сделать платформа автоматически если возле методов, которые будут вызываться удаленно, ставить аннотации.
2) JavaBeans должны сопровождаться классами BeanInfo. А EJB дескриптором развертования. Продуктивнее и более безопасно в плане ошибок, чтобы эти файлы генерировались на основании аннотаций в коде автоматически.
Есть и много других полезных старых анотаций:
- @transient -- ставится возле параметров класса, который не нужно серилизировать.
- @depracated -- ставится возле методов, которые лучше не использовать.
Анотации очень похожы на javadoc, они даже дополняют их, но между ними есть четкое отличие. Вторые используются только для автоматической генерации документаций. А первые влият на работу программы (хотя не через саму семантику программы, а влияя на интрументарий jdk и на библиотеки).
Анотации мы можем счиатать из исходников, откомпилированных классов и даже из обьектов на этапе выполнения приложения.
Чтобы создать собственную аннотацию, мы должны ее описать, и сделать для нее собственный процессор, а также указать этот процессор в файле архива
META-INF/services/javax.annotation.processing.Processor, в этом файле указываются все кастомные процессоры(пакетный путь на их классы через перенос строки). Для примера собственной аннотации придумаем себе задачу и решим ее. Этот пример взят из http://www.javaspecialists.eu/archive/Issue167.html.
Допустим нам нужно в определенных классах обеспечить, чтобы они имели полюбому публичный контсруктор без аргументом, при этом выявить такие классы мы должны не тестируя откомпилированное приложение, а на этапе компиляции(по-этому вопрос с исключениями сразу отпадает).
Первое опишем аннотацию:
package eu.javaspecialists.tools.apt; import java.lang.annotation.*; @Inherited @Documented @Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) public @interface NoArgsConstructor { }
Как видим в описании аннотации уже используются готовые аннотации) Разберем их:
@Inherited - означает, что наследники класса, к которому применена аннотация, наследывают и аннотацию тоже.
@Documented - означает, что в документацию javadoc будет заносить эту аннотацию.
@Retention(RetentionPolicy.SOURCE) - означает, что аннотация будет доступна только на этапе компиляции(или запуска apt), в момент работы приложения аннотация не доступна.
@Target(ElementType.TYP) - означает, что эта аннотация применима только к классам.
Теперь пришло время создать файл процессора для нашей аннотации:
package eu.javaspecialists.tools.apt; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; import javax.lang.model.element.*; import javax.lang.model.type.*; import javax.lang.model.util.SimpleTypeVisitor6; import javax.tools.Diagnostic; import java.util.Set; @SupportedAnnotationTypes( "eu.javaspecialists.tools.apt.NoArgsConstructor") @SupportedSourceVersion(SourceVersion.RELEASE_6) public class NoArgsConstructorProcessor extends AbstractProcessor { public boolean process(Setextends TypeElement> annotations, RoundEnvironment env) { for (TypeElement type : annotations) { processNoArgsConstructorClasses(env, type); } return true; } private void processNoArgsConstructorClasses( RoundEnvironment env, TypeElement type) { for (Element element : env.getElementsAnnotatedWith(type)) { processClass(element); } } private void processClass(Element element) { if (!doesClassContainNoArgsConstructor(element)) { processingEnv.getMessager().printMessage( Diagnostic.Kind.ERROR, "Class " + element + " needs a No-Args Constructor"); } } private boolean doesClassContainNoArgsConstructor(Element el) { for (Element subelement : el.getEnclosedElements()) { if (subelement.getKind() == ElementKind.CONSTRUCTOR && subelement.getModifiers().contains(Modifier.PUBLIC)) { TypeMirror mirror = subelement.asType(); if (mirror.accept(noArgsVisitor, null)) return true; } } return false; } private static final TypeVisitornoArgsVisitor = new SimpleTypeVisitor6 () { public Boolean visitExecutable(ExecutableType t, Void v) { return t.getParameterTypes().isEmpty(); } }; }
Запакуем наши созданные файлы для аннотации в архивчик apttools.jar, при этом не забудем в нем создать файл
META-INF/services/javax.annotation.processing.Processor, а внем вписать строку:eu.javaspecialists.tools.apt.NoArgsConstructorProcessor
А теперь создадим код для тестирования нашей аннотации:
import eu.javaspecialists.tools.apt.NoArgsConstructor; @NoArgsConstructor public abstract class NoArgsSuperClass { public NoArgsSuperClass() { } } // Passes public class PublicNoArgsConstructor extends NoArgsSuperClass { public PublicNoArgsConstructor() { } } // Passes public class DefaultConstructor extends NoArgsSuperClass { } // Passes public class SeveralConstructors extends NoArgsSuperClass { public SeveralConstructors(String as) { } public SeveralConstructors(int ai) { } public SeveralConstructors() { } } // Fails public class NonPublicConstructor extends NoArgsSuperClass { NonPublicConstructor() { } } // Fails public class WrongConstructor extends NoArgsSuperClass { public WrongConstructor(String aString) { } }
И попрообуем его откомпилировать с учетом наших аннотаций:
javac -classpath .;apttools.jar -processorpath apttools.jar *.java
В результате получим следующий результат в консоли:
error: Class NonPublicConstructor needs a No-Args Constructor
error: Class WrongConstructor needs a No-Args Constructor
2 errors
Комментариев нет:
Отправить комментарий