Как использовать byte buddy для создания класса ленивой загрузки?

У нас есть большой класс (сотни методов), интерфейс которого снабжен рекомендациями по ленивой загрузке. При первоначальной загрузке этого объекта и отправке его клиенту мы делаем ограниченную загрузку наиболее часто используемых и последних данных. В настоящее время мы используем java Proxying для прослушивания каждого вызова. При каждом вызове мы проверяем «Есть ли у нас данные? Если есть параметр даты, загрузили ли мы данные для этой даты?» Если ответ отрицательный на любой из этих вопросов, мы возвращаемся к серверу и загружаем полный объект.

Это работает, однако отражение java, проксирование и дополнительные накладные расходы на вызовы, такие как базовые геттеры (например, getId()), отрицательно влияют на производительность некоторого нашего кода.

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

Как лучше всего подойти к этому?

Кроме того, поскольку этот объект сериализуется (сериализация Java, сервер создает эти объекты и передает их клиенту), как правильно убедиться, что эти динамически созданные классы могут передаваться от сервера к клиенту по сети?


person Cogman    schedule 11.06.2015    source источник


Ответы (1)


Одна вещь, которую вы можете сделать по-другому, используя Byte Buddy, — это по-разному перехватывать разные методы. Таким образом, вы можете учитывать доступные данные при создании прокси, а не откладывать это до времени выполнения. Например:

interface Foo {

  Object simpleProperty();

  @Lazy
  Object complexProperty();

  @Lazy
  Object timedProperty(Date date);
}

Вы можете написать перехватчик, который соответствует любому из методов:

new ByteBuddy()
  .subclass(Foo.class)
  .method(any()).
    intercept(directValueInterceptor)
  .method(isAnnotatedBy(Lazy.class))
    .intercept(lazyValueInterceptor)
  .method(isAnnotatedBy(Lazy.class).and(takesArguments(Date.class))
    .intercept(lazyTimedInterceptor)

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

person Rafael Winterhalter    schedule 11.06.2015
comment
Как бы вы предложили мне выполнить загрузку данных? Прямо сейчас мы сохраняем в прокси частично загруженный объект и вызываем Method.invoke для этого объекта. Когда происходит событие загрузки, мы просто меняем частично загруженный объект на полностью загруженный. - person Cogman; 11.06.2015
comment
Посмотрите на аннотацию @Pipe. Это позволяет вам избежать упаковки, которая обычно вызывает проблемы с производительностью. - person Rafael Winterhalter; 11.06.2015