2010-11-05 4 views
30

Я хочу получить полный список классов в приложении, которые аннотируются аннотацией @Custom. Каков наилучший механизм для этой операции?Как создать список классов, аннотированных моей пользовательской аннотацией?

пс. Например, как реализации JAX-RS находят все классы, аннотированные с помощью @Path? Я хотел бы использовать тот же механизм.

+0

Вы используете IDE? – thejh

+0

Вы хотите найти в исходном коде (.java) или в скомпилированном коде (.class)? –

+0

Нет, я не использую IDE. Меня интересует только скомпилированный код в моем JAR. – yegor256

ответ

0

Запустите поиск в вашей среде IDE на источнике. Если вы попытаетесь сделать это на скомпилированных классах, вы бы добавили к ним метод, чтобы поддержать это, даже если вы декомпилировали классы, которые я не думаю, что аннотации или комментарии будут отображаться вверх.

+1

Аннотации отображаются в байт-коде java –

+0

@Brian да, если '@ Retention' аннотации' 'RUNTIME' –

+0

... если они определены с помощью' @Retention (RUNTIME) ' –

2

Как вы, наверное, уже знаете, Java не имеет возможности перечислять все пакеты или классы в каждом пакете. Поэтому вы должны сделать это «жестким» способом. Варианты:

  1. Используйте инструмент, например grep, для поиска аннотации. Преимущество: быстрая, простая. Недостатки: может возвращать ложные срабатывания (например, классы, в которых комментарий комментируется).

  2. Скомпилируйте код и обработайте результат javap. Это работает на уровне байт-кода [*]. Он дает точные результаты, но вывод javap на самом деле не предназначен для автоматической обработки.

  3. Используйте библиотеку байт-кода, например ASM. Не для слабонервных, но он также позволяет вам получать доступ к другим данным (например, реализованные интерфейсы, поля и т. Д.) В отношении аннотации.

  4. Последняя опция: Eclipse использует свой собственный Java-компилятор, который может построить код AST из Java (даже если код не компилируется). Преимущество над ASM: вы бесплатно получаете модель для Java-кода. Делает определенные операции более простыми. Но так легко настроить. See my blog for an example.

[*]: аннотация должна содержать Retention.RUNTIME, чтобы это сработало.

+0

Первый вариант = arggghh. Все остальные: +1 –

+0

Какие из ваших вариантов реализации JAX-RS используют, например, Джерси, чтобы найти все классы, посвященные '@ Path'-annotated? – yegor256

+0

Заботьтесь о том, чтобы доказать свою претензию, что нет способа? Особенно в свете библиотеки, с которой я связался в своем ответе? – meriton

0

Самый простой способ - использовать IDE as Jesus suggested.

Но вы также можете

  • написать annotation processor который регистрирует все вхождения аннотации
  • написать аспект AspectJ и declare a warning for this annotation (я знаю, предупреждение, вероятно, не то, что вы хотите, но нет INFO в AspectJ)
  • использования ASM проверить байт-код для аннотирования
  • использования a Source Parser проверить исходный код для аннотирования

Остерегайтесь: все это сложно. Решение AspectJ должно быть самым простым.

3

Вы должны взглянуть на Scannotation.

+0

Кажется хорошим вариантом. Я попробую позже – rpax

21

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

Этот подход реализуется библиотеками, такими как Scannotation и Reflections.

Другой подход заключается в использовании Java Pluggable Annotation Processing API для написания обработчика аннотаций, который будет собирать все аннотированные классы во время компиляции и создавать индексный файл для использования во время выполнения.

Вышеупомянутый механизм реализован в библиотеке ClassIndex.

Использование сканирования на основе классов обычно на два порядка медленнее, чем индексирование во время компиляции. См. this benchmark.

10

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

Google Guava имеет объект ClassPath, который обеспечивает сканирование по методу «лучшее усилие» (это все, что действительно предлагает утилита сканирования классов). Поскольку Guava является широко принятой, тщательно укомплектованной библиотекой утилиты, это отличный вариант для проектов, которые либо (а) уже используют Guava, либо (b) нуждаются в стабильной библиотеке, на которую они могут положиться для сканирования пути к классам.

1

classindex - это библиотека сканирования аннотаций времени компиляции, реализованная с использованием обработчика аннотаций.

3

Вы могли бы попробовать мою библиотеку FastClasspathScanner:

List<String> classNames = new FastClassPathScanner("com.mypackage") 
    .scan() 
    .getNamesOfClassesWithAnnotation(Custom.class); 
Смежные вопросы