Рубрики
Без рубрики

Путеводитель по библиотеке отражений

Узнайте, как настроить библиотеку отражений и использовать ее в своих проектах Java

Автор оригинала: baeldung.

1. Введение

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

В этом уроке мы покажем, как настроить библиотеку Reflections и использовать ее в наших Java-проектах.

2. Зависимость Maven

Чтобы использовать Reflections , нам нужно включить его зависимость в наш проект:


    org.reflections
    reflections
    0.9.11

Мы можем найти последнюю версию библиотеки на Maven Central .

3. Настройка отражений

Далее нам нужно настроить библиотеку. Основными элементами конфигурации являются URL-адреса и сканеры.

URL-адреса сообщают библиотеке, какие части пути к классам следует сканировать, в то время как сканеры-это объекты, которые сканируют данные URL-адреса.

В том случае, если сканер не настроен, библиотека использует TypeAnnotationsScanner и SubTypesScanner в качестве стандартных.

3.1. Добавление URL-адресов

Мы можем настроить Reflections либо предоставив элементы конфигурации в качестве параметров конструктора varargs, либо используя объект ConfigurationBuilder .

Например, мы можем добавить URL-адреса, создав экземпляр Reflections с помощью строки , представляющей имя пакета, класс или загрузчик классов:

Reflections reflections = new Reflections("com.baeldung.reflections");
Reflections reflections = new Reflections(MyClass.class);
Reflections reflections = new Reflections(MyClass.class.getClassLoader());

Более того, поскольку Reflections имеет конструктор varargs, мы можем объединить все вышеперечисленные типы конфигураций для его создания:

Reflections reflections = new Reflections("com.baeldung.reflections", MyClass.class);

Здесь мы добавляем URL-адреса, указывая пакет и класс для сканирования.

Мы можем достичь тех же результатов, используя Конструктор конфигураций :

Reflections reflections = new Reflections(new ConfigurationBuilder()
  .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections"))));

Вместе с методом for Package () , Classp ath Helpe r предоставляет другие методы , такие как for Class() и forClassLoader () , для добавления URL-адресов в конфигурацию.

3.2. Добавление Сканеров

Библиотека Reflections поставляется со многими встроенными сканерами:

  • FieldAnnotationsScanner – ищет аннотации поля
  • MethodParameterScanner – сканирует методы/конструкторы, затем индексирует параметры и возвращает аннотации типов и параметров
  • MethodParameterNamesScanner – проверяет методы/конструкторы, а затем индексирует имена параметров
  • TypeElementsScanner – проверяет поля и методы, затем сохраняет полное имя в качестве ключа, а элементы-в качестве значений
  • MemberUsageScanner – сканирует методы/конструкторы/поля использования
  • TypeAnnotationsScanner – ищет аннотации времени выполнения класса
  • SubTypesScanner – ищет супер классы и интерфейсы класса, позволяя обратный поиск подтипов
  • MethodAnnotationsScanner – сканирует аннотации метода
  • ResourcesScanner – собирает все неклассовые ресурсы в коллекцию

Мы можем добавить сканеры в конфигурацию в качестве параметров конструктора Reflections .

Например, давайте добавим первые два сканера из приведенного выше списка:

Reflections reflections = new Reflections("com.baeldung.reflections"), 
  new FieldAnnotationsScanner(), 
  new MethodParameterScanner());

Опять же, эти два сканера можно настроить с помощью класса Configuration Builder helper:

Reflections reflections = new Reflections(new ConfigurationBuilder()
  .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections"))
  .setScanners(new FieldAnnotationsScanner(), new MethodParameterScanner()));

3.3. Добавление службы ExecutorService

В дополнение к URL-адресам и сканерам, Reflections дает нам возможность асинхронно сканировать путь к классу с помощью ExecutorService .

Мы можем добавить его как параметр конструктора Reflections ‘ или через Configuration Builder :

Reflections reflections = new Reflections(new ConfigurationBuilder()
  .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections"))
  .setScanners(new SubTypesScanner(), new TypeAnnotationsScanner())
  .setExecutorService(Executors.newFixedThreadPool(4)));

Другой вариант-просто вызвать метод use ParallelExecutor () . Этот метод настраивает значение по умолчанию FixedThreadPool ExecutorService с размером, равным количеству доступных процессоров ядра.

3.4. Добавление фильтров

Еще одним важным элементом конфигурации является фильтр. Фильтр сообщает сканерам, что включать и что исключать при сканировании пути к классу .

В качестве иллюстрации мы можем настроить фильтр так, чтобы исключить сканирование тестового пакета:

Reflections reflections = new Reflections(new ConfigurationBuilder()
  .setUrls(ClasspathHelper.forPackage("com.baeldung.reflections"))
  .setScanners(new SubTypesScanner(), new TypeAnnotationsScanner())
  .filterInputsBy(new FilterBuilder().excludePackage("com.baeldung.reflections.test")));

Теперь, до этого момента, мы сделали краткий обзор различных элементов конфигурации Reflections . Далее мы посмотрим, как пользоваться библиотекой.

4. Запрос С Использованием Отражений

После вызова одного из конструкторов Reflections настроенные сканеры сканируют все предоставленные URL-адреса. Затем для каждого сканера библиотека помещает результаты в Multimap stores . В результате, чтобы использовать Reflections , нам нужно запросить эти хранилища, вызвав предоставленные методы запроса.

Давайте рассмотрим некоторые примеры этих методов запроса.

4.1. Подтипы

Давайте начнем с извлечения всех сканеров, предоставленных Reflections :

public Set> getReflectionsSubTypes() {
    Reflections reflections = new Reflections(
      "org.reflections", new SubTypesScanner());
    return reflections.getSubTypesOf(Scanner.class);
}

4.2. Аннотированные типы

Далее мы можем получить все классы и интерфейсы, реализующие данную аннотацию.

Итак, давайте извлекем все функциональные интерфейсы пакета java.util.function :

public Set> getJDKFunctinalInterfaces() {
    Reflections reflections = new Reflections("java.util.function", 
      new TypeAnnotationsScanner());
    return reflections.getTypesAnnotatedWith(FunctionalInterface.class);
}

4.3. Аннотированные Методы

Теперь давайте используем MethodAnnotationsScanner , чтобы получить все методы, аннотированные данной аннотацией:

public Set getDateDeprecatedMethods() {
    Reflections reflections = new Reflections(
      "java.util.Date", 
      new MethodAnnotationsScanner());
    return reflections.getMethodsAnnotatedWith(Deprecated.class);
}

4.4. Аннотированные конструкторы

Кроме того, мы можем получить все устаревшие конструкторы:

public Set getDateDeprecatedConstructors() {
    Reflections reflections = new Reflections(
      "java.util.Date", 
      new MethodAnnotationsScanner());
    return reflections.getConstructorsAnnotatedWith(Deprecated.class);
}

4.5. Параметры методов

Кроме того, мы можем использовать Method Parameter Scanner для поиска всех методов с заданным типом параметра:

public Set getMethodsWithDateParam() {
    Reflections reflections = new Reflections(
      java.text.SimpleDateFormat.class, 
      new MethodParameterScanner());
    return reflections.getMethodsMatchParams(Date.class);
}

4.6. Тип возвращаемого значения методов

Кроме того, мы также можем использовать один и тот же сканер, чтобы получить все методы с заданным типом возврата.

Давайте представим, что мы хотим найти все методы SimpleDateFormat , которые возвращают void :

public Set getMethodsWithVoidReturn() {
    Reflections reflections = new Reflections(
      "java.text.SimpleDateFormat", 
      new MethodParameterScanner());
    return reflections.getMethodsReturn(void.class);
}

4.7. Ресурсы

Наконец, давайте используем Resources Scanner для поиска заданного имени файла в вашем пути к классу:

public Set getPomXmlPaths() {
    Reflections reflections = new Reflections(new ResourcesScanner());
    return reflections.getResources(Pattern.compile(".*pom\\.xml"));
}

4.8. Дополнительные Методы Запроса

Выше было приведено лишь несколько примеров, показывающих, как использовать методы запросов Reflections’ . Тем не менее, есть и другие методы запроса, которые мы здесь не рассматривали:

  • получить Методы С Любым Аннотированным Параметром
  • getConstructors Соответствуют парам
  • getConstructorsWithAnyParamAnnotated
  • getFieldsAnnotatedWith
  • получить MethodParamNames
  • getConstructor Param Names
  • Использование getField
  • использование метода get
  • Использование getConstructor

5. Интеграция отражений в жизненный цикл сборки

Мы можем легко интегрировать Reflections в нашу сборку Maven с помощью gmavenplus-plugin .

Давайте настроим его так, чтобы он сохранял результат сканирования в файл:


    org.codehaus.gmavenplus
    gmavenplus-plugin
    1.5
    
        
            generate-resources
            
                execute
            
            
                
                    
                
            
        
    

Позже, вызвав метод collect () , мы можем получить сохраненные результаты | и сделать их доступными для дальнейшего использования без необходимости выполнять новое сканирование:

Reflections reflections
  = isProduction() ? Reflections.collect() : new Reflections("com.baeldung.reflections");

6. Заключение

В этой статье мы исследовали библиотеку Reflections . Мы рассмотрели различные элементы конфигурации и их использование. И, наконец, мы увидели, как интегрировать Reflections в жизненный цикл сборки проекта Maven.

Как всегда, полный код доступен на GitHub .