Недостатки обработки аннотаций в Java? - PullRequest
29 голосов
/ 27 марта 2009

Я рассматриваю возможность запуска проекта, который используется для генерации кода в Java с использованием аннотаций (я не буду вдаваться в подробности, так как это не очень актуально). Меня интересует обоснованность и полезность проекта, и что меня поразило, так это зависимость от Annontation Processor Tool (apt).

Что я хотел бы знать, как я не могу сказать из опыта, каковы недостатки использования обработки аннотаций в Java?

Это может быть что угодно, в том числе:

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

Это всего лишь примеры, а не мое мнение. Я нахожусь в процессе исследования, если что-то из этого является правдой (включая задание этого вопроса ;-))

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

Единственной разумной альтернативой использованию обработки аннотаций, вероятно, является создание плагинов для соответствующих IDE для генерации кода (это было бы чем-то неопределенно похожим на функцию переопределения / реализации методов, которая генерировала бы все подписи без тел методов). Однако этот шаг должен повторяться каждый раз, когда изменяются соответствующие части кода, обработка аннотаций не будет, насколько я могу судить.

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

Ответы [ 3 ]

30 голосов
/ 01 апреля 2009

Я создал набор аннотаций JavaBean (http://code.google.com/p/javadude/wiki/Annotations)

[Примечание: я сейчас работаю над новой версией, поэтому код транка не соответствует загрузкам с сайта обновления]

Тестирование

Тестировать их можно довольно сложно ...

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

Затем я могу использовать Eclipse для сравнения «активного» тестового проекта с «ожидаемой» копией проекта.

У меня пока не так много тестов (очень сложно создавать так много комбинаций атрибутов), но это помогает.

Сборка системы

Использование аннотаций в системе сборки на самом деле очень просто. Взгляните на http://code.google.com/p/javadude/wiki/Annotations для примера того, как он используется в скрипте ant, и использование его в eclipse - это всего лишь вопрос создания плагина, задающего расширение процессора аннотаций и включающего обработку аннотаций в проектах, которые хотят используйте это.

Я использовал обработку аннотаций в среде непрерывной сборки, собирал аннотации и процессор, а затем использовал их в остальной части сборки. Это действительно довольно безболезненно.

Время обработки

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

Обратите внимание, что процессоры Java6 могут работать немного быстрее, потому что они являются частью обычного процесса компиляции. Однако у меня возникли проблемы с тем, чтобы заставить их работать должным образом с возможностью генерации кода (я думаю, что большая часть проблемы заключается в поддержке eclipse и запуске многофазных компиляций). Сейчас я придерживаюсь Java 5.

Ошибка обработки

Это одна из самых продуманных вещей в API аннотаций. В API есть объект "messenger", который обрабатывает все ошибки. Каждая IDE предоставляет реализацию, которая преобразует это в соответствующие сообщения об ошибках в нужном месте кода.

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

Генерация кода Gotcha

[добавлено немного больше за комментарии]

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

Однако вы можете генерировать другие классы, и они рекомендуют такой подход.

Я генерирую суперкласс для всех методов get / set и всего, что мне нужно сгенерировать. У меня также есть процессор, чтобы убедиться, что аннотированный класс расширяет сгенерированный класс. Например:

@Bean(...)
public class Foo extends FooGen

Я создаю класс в том же пакете с именем аннотированного класса плюс «Gen» и проверяю, что аннотированный класс объявлен для его расширения.

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

Я бы порекомендовал создать суперкласс.

В целом

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

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

Обратите внимание, что API для процессоров аннотаций Java 5 и Java 6 отличается! API обработки Java 6 лучше IMHO, но мне просто не повезло с процессорами Java 6, делающими то, что мне нужно.

Когда выйдет Java 7, я сделаю новый подход к обработке еще раз.

Не стесняйтесь, напишите мне, если у вас есть вопросы. (Scott@javadude.com)

Надеюсь, это поможет!

6 голосов
/ 04 февраля 2010

Я думаю, что если процессор аннотаций определенно использует версию API Java 6. Это тот, который будет поддерживаться в будущем. API Java 5 все еще находился в неофициальном пространстве имен com.sun.xyz.

Я думаю, что мы увидим гораздо больше использования API процессора аннотаций в ближайшем будущем. Например, Hibernate разрабатывает процессор для новой функциональности статической метамодели, связанной с запросом JPA 2. Они также разрабатывают процессор для проверки аннотаций Bean Validation. Так что обработка аннотаций здесь, чтобы остаться.

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

Тестирование Я нахожу большую проблему, хотя. Все тесты являются косвенными и каким-то образом проверяют конечный результат обработки аннотации. Я не могу написать ни одного простого модульного теста, который просто утверждает простые методы, работающие с TypeMirrors или другими классами, основанными на отражении. Проблема в том, что нельзя создавать экземпляры этих классов вне цикла компиляции процессоров. Я не думаю, что Sun действительно имела в виду тестируемость при разработке API.

2 голосов
/ 27 марта 2009

Один конкретный, который будет полезен при ответе на вопрос, будет в отличие от чего? Не выполняете проект или не используете аннотации? И если не использовать аннотации, каковы альтернативы?

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

    @WebMethod(action=QBWSBean.NS+"receiveResponseXML")
@WebResult(name="receiveResponseXML"+result,targetNamespace = QBWSBean.NS)
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public int receiveResponseXML(
        @WebParam(name = "ticket",targetNamespace = QBWSBean.NS) String ticket,
        @WebParam(name = "response",targetNamespace = QBWSBean.NS) String response,
        @WebParam(name = "hresult",targetNamespace = QBWSBean.NS) String hresult,
        @WebParam(name = "message",targetNamespace = QBWSBean.NS) String message) {

Я считаю этот код крайне нечитаемым. Хотя альтернатива конфигурации XML не обязательно лучше.

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