How do I use byte buddy to create a lazy loading class?

752 views Asked by At

We have a large class (100s of methods) which has an interface annotated with lazy loading guidelines. When initially loading this object and sending it to the client we do a limited load of the most frequently used and recent data. We are currently using java Proxying to sniff on every invocation. On every invocation we are checking "Do we have the data? If there is a date param, have we loaded data for that date?" If the answer is no to either of those questions we go back to the server and load the full object.

This works, however, the java reflection, proxying, and the extra overhead on calls like basic getters (getId() for example) plays havoc on the performance of some of our code.

I want to start using byte buddy to hopefully decrease the invocation costs, especially on the simple fields that are always loaded.

What is the best way to approach this?

Also, because this object is being serialized (Java serialization, The server makes these objects and hands them off to the client), what is the right way to make sure these dynamically created classes can be passed from server to client across the wire?

1

There are 1 answers

2
Rafael Winterhalter On

One thing you can do differently using Byte Buddy is to intercept different methods in a different way. This way, you can take the available data into consideration while creating the proxy instead of delaying this until runtime. For example:

interface Foo {

  Object simpleProperty();

  @Lazy
  Object complexProperty();

  @Lazy
  Object timedProperty(Date date);
}

You could write an interceptor that matches any of the methods:

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)

The matchers are applied reverse in their order, meaning that a method that is annotated by Lazy and takes an argument Date is intercepted by the last interceptor while a method that is not annotated is matched by the first interceptor. This way, you can write specialized interceptors that operate on the made assumption of how to return a value and you do not longer need to introspect at runtime.