Как написать процессор аннотаций Java?
Возможно, я просто смотрю в неправильном направлении, но я нахожу документацию JSE по обработке аннотаций очень... редкой. Я хочу написать обработчик аннотаций, который обрабатывает аннотированные строковые поля и локальные переменные, чтобы заменить их вычисленным строковым выражением. Это не должно быть слишком сложно, но я довольно потерян в Javadoc для обработки javax.annotation.processing.
РЕДАКТИРОВАТЬ: мне нужно обрабатывать аннотации во время компиляции, потому что я хочу изменить сгенерированный код. Следует заменить аннотированные константные строковые выражения вычисляемым строковым выражением.
3 ответа
Это не может быть сделано с процессором аннотации времени компиляции. Процессоры аннотаций времени компиляции могут генерировать только новые файлы (и классы), но не могут изменять существующие классы. Вы можете делать рефлексию во время выполнения, но строго говоря, это не называется обработкой аннотаций. Также у вас не будет доступа к локальным переменным.
Если вы ищете, как написать процессор аннотаций времени компиляции, посмотрите https://github.com/pellaton/spring-configuration-validation-processor
Два инструмента, которые делают это, это Project Lombok и DuctileJ. Оба этих инструмента существовали в то время, когда вопрос был задан изначально; дополнительные инструменты сейчас наверняка существуют.
Основная идея заключается в написании процессора аннотаций, который просматривает и изменяет AST (абстрактное синтаксическое дерево) программы во время компиляции перед генерацией кода. Компилятор не будет изменять исходный код на диске, но сгенерированный файл.class будет отражать изменения, которые вносит ваш процессор аннотаций.
Возможно, вам удастся адаптировать один из этих инструментов в соответствии с вашими потребностями, или вы можете реализовать свой собственный инструмент, основанный на их методах реализации.
Обработка во время компиляции имеет два преимущества по сравнению с обработкой файла класса. Во-первых, компилятор обычно имеет больше информации, чем доступно из скомпилированного кода. Другой заключается в том, что все происходит за один шаг во время компиляции, а не требует от разработчика запуска отдельного инструмента для перезаписи файлов.class после компиляции.
Проверьте
- Джавассист http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
- ASM http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
- Байтмен (для времени выполнения) http://www.jboss.org/byteman/