Сканирование аннотаций

Как я уже писал, аннотации в Java это просто метки в коде, которые находятся и анализируются другим кодом. А, следовательно, недостаточно уметь просто создавать аннотации, надо научиться и находить неизвестный код, который ими аннотирован. И, к сожалению, это довольно непросто.

Подготовка

Возьмём пустой maven проект и добавим в него незамысловатую аннотацию:

К ней создадим простой класс, на который аннотацию и навесим. Так как класс нужен только как место для использования аннотации, содержимое класса совершенно не важно и не нужно:

Сканирование classpath

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

Строки 2-3 функции manualScan() получают имя пакета для текущего класса. Мы будем загружать классы только из этого пакета, чтобы не пробовать все доступные классы JRE. В строках 5-8 у текущего class loader запрашивается список путей, входящих в classpath. Наконец в 14 строке этот список преобразуется функцией findClasses, которая просматривает каждый каталог из classpath на наличие файлов с суффиксом .class и пытается их загрузить. Так же эта функция рекурсивно вызывает саму себя, наткнувшись на каталог. И вся эта машинерия нужна только для того, чтобы загрузить список классов! Более того, конкретно этот код будет работать только в очень простых случаях и не справится даже с jar файлом 🙁

Наконец, в строках 15-21, проверяется, есть ли у класса нужна аннотация и, если она есть, её значение достаётся из класса и печатается. Именно в этом месте вы можете вставить собственную логику работы с аннотацией.

Используем Reflections

К счастью в мире java есть более 9000 библиотек на все случаи жизни, есть и библиотека для сканирования классов на аннотации (и не только). Добавим библиотеку Reflectlions к нашему maven проекту:

Сканирование классов сводится к двум вызовам — создаём объект Reflections, которому указываем, с каким пакетом работать и запрашиваем у него нужные классы:

Полученный список классов так же используется для получения значений аннотации.

Код примера доступен на github