Java: Какой самый быстрый способ ввода полей с помощью отражения? - PullRequest
5 голосов
/ 28 октября 2009

Предположим, у меня есть много классов, которые построены с использованием отражения Java (по некоторым причинам). Теперь мне нужно добавить значения в поля, которые отмечены @PostInject.

public class SomeClass {
  @PostInject
  private final String someString = null;

  public void someMethod() {
    // here, someString has a value.
  }
}

У меня вопрос: Что такое быстрый способ задания поля с помощью отражения?
Помните, мне нужно делать это очень часто на многих уроках, это почему производительность важна.

Что бы я делал интуицией, показывает этот псевдокод:

  • получить все поля класса
    clazz.getFields();
  • чек, помеченный @ PostInject
    eachField.getAnnotation(PostInject.class);
  • сделать эти поля доступными
    eachAnnotatedField.setAccessible(true);
  • установить их на определенное значение
    eachAnnotatedField.set(clazz, someValue);

Боюсь, что заполнить все поля - самая медленная вещь.
Могу ли я получить поле, если я знаю его с самого начала?

ПРИМЕЧАНИЕ: я не могу просто позволить классам реализовать некоторый интерфейс, который бы позволяют устанавливать поля, используя метод. Мне нужно POJO.

ПРИМЕЧАНИЕ 2. Почему я хочу использовать инъекцию после поля: с точки зрения пользователя API, должна быть возможность использовать конечные поля. Кроме того, когда API априори не знает типы и количество полей, невозможно выполнить инициализацию полей с помощью интерфейса.

ПРИМЕЧАНИЕ2b: С точки зрения пользователя, окончательный контракт не нарушен. Это остается окончательным. Сначала поле инициализируется, затем его нельзя изменить. Кстати, есть много API, которые используют эту концепцию, одним из них является JAXB (часть JDK).

Ответы [ 5 ]

7 голосов
/ 28 октября 2009

Как насчет выполнения шагов с 1 по 3 сразу после создания объекта и сохранения набора аннотированных полей, которые вы получаете либо в самом объекте, либо сохраняя отдельную карту класса для набора аннотированных полей?

Затем, когда вам нужно обновить введенные поля в объекте, получить набор из объекта или отдельной карты и выполнить шаг 4.

1 голос
/ 28 октября 2009

Не знаю, хорошо ли это, но этот проект выглядит так, как будто он будет делать то, что вы хотите. Цитата:

Набор утилит отражения и различные утилиты, связанные с работа с классами и их полями без каких-либо зависимостей, который совместим с Java 1.5 и дженериками.

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

1 голос
/ 28 октября 2009

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

Пример: см. getDeclaredMethod или getDeclaredField в java / lang / Class.html

0 голосов
/ 28 октября 2009

Самый быстрый способ сделать что-либо с помощью отражения - это кэшировать реальные классы API Reflection, когда это возможно. Например, я совсем недавно создал еще один динамический POJO-манипулятор, который, я считаю, является одной из тех вещей, которые все заканчивают в какой-то момент, что позволяет мне сделать это:

Object o = ...
BeanPropertyController c = BeanPropertyController.of(o);

for (String propertyName : c.getPropertyNames()) {
        if (c.access(propertyName) == null && 
            c.typeOf(propertyName).equals(String.class)) {
                c.mutate(propertyName, "");
        }
}

Способ, которым он работает, заключается в том, что он в основном имеет тот один объект контроллера, который лениво загружает все свойства бина ( примечание: некоторая магия задействована ) и затем использует их до тех пор, пока фактический объект контроллера жив , Все, что я могу сказать, это то, что, просто сохранив сами объекты Метода, мне удалось превратить эту вещь в чертовски быструю вещь, и я очень горжусь ею, и даже рассматриваю возможность ее выпуска, предполагая, что смогу разобраться с авторскими правами и т. Д.

0 голосов
/ 28 октября 2009

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

...