2009-10-28 2 views
5

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

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 априори, невозможно осуществить инициализацию поля с использованием интерфейса.

NOTE2b: С точки зрения пользователя, окончательный контракт не сломана. Он остается окончательным. Во-первых, поле инициализируется, тогда его нельзя изменить. Кстати, есть много API, которые используют эту концепцию, один из которых - JAXB (часть JDK).

+0

Мне просто интересно, зачем вам это нужно? Есть ли интересная история за этим, и если есть, можете ли вы поделиться ею? –

+0

Я пишу marshaller | unmarshaller, похожий на JAXB, но более специальный (таким образом, более ограниченный). POJO с аннотациями просто очень гибкие. –

+1

Если вы хотите, чтобы разработчики использовали вашу аннотацию - вы на самом деле ничего не получаете от использования интерфейса здесь, и вы на самом деле не используете POJO - http://en.wikipedia.org/wiki/Plain_Old_Java_Object#Contextual_variations – Nate

ответ

7

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

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

+0

Идеальная идея !!! –

1

+1 Мне нравится идея RSP в.


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

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

1

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

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

данные отражения

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

0

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

0

Самый быстрый способ сделать что-либо с отражением - это кэшировать фактические классы 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, ""); 
     } 
} 

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

Смежные вопросы