Java Deep

Pure Java, what else

Creating a proxy object using cglib

In the previous post I was talking about the standard Java based proxy objects. These can be used when you want to have a method invocation handler on an object that implements an interface. The Java reflection proxy creation demands that you have an object that implements the interface. The object we want to proxy is out of our hand, it does not implement the interface that we want to invoke from our handler and still we want to have a proxy.

When do we need proxy to objects w/o interface?

This is a very common case. If ever we have a JPA implementation e.g. Hibernate that implements lazy loading of the records. For example the audit log records are stored in a table and each record, except the first one has a reference to the previous item. Something like

class LinkedAuditLogRecord {
  LinkedAuditLogRecord previous;
  AuditLogRecord actualRecord;
}

Loading a record via JPA will return an object LinkedAuditLogRecord which contains the previous record as an object and so on until the first one that probably has null in the field named previos. (This is not an actual code.) Any JPA implementation grabbing and loading the whole table from the start to the record of our interest would be an extremely poor implementation. Instead the persistence layer loads the actual record only and creates a proxy object extending LinkedAuditLogRecord and that is what the field previous is going to be. The actual fields are usually private fields and if ever our code tries to access the previous record the proxy object will load it that time. This is lazy loading in short.

But how do the JPA implementations create proxies to objects of classes that do not implement interfaces? Java reflection proxy implementation can not do that and thus JPA implementation uses something different. What they usually use is cglib.

What is cglib

Cglib is an open source library that capable creating and loading class files in memory during Java run time. To do that it uses Java byte-code generation library ‘asm’, which is a very low level byte code creation tool. I will not dig that deep in this article.

How to use cglib

To create a proxy object using cglib is almost as simple as using the JDK reflection proxy API. I created the same code as the last week article, this time using cglib:

package proxy;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxyDemo {

    static class Original {
        public void originalMethod(String s) {
            System.out.println(s);
        }
    }

    static class Handler implements MethodInterceptor {
        private final Original original;

        public Handler(Original original) {
            this.original = original;
        }

        public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("BEFORE");
            method.invoke(original, args);
            System.out.println("AFTER");
            return null;
        }
    }

    public static void main(String[] args){
        Original original = new Original();
        MethodInterceptor handler = new Handler(original);
        Original f = (Original) Enhancer.create(Original.class,handler);
        f.originalMethod("Hallo");
    }
}

The difference is that name of the classes are a bit different and we do not have an interface.

It is also important that the proxy class extends the original class and thus when the proxy object is created it invokes the constructor of the original class. In case this is resource hungry we may have some issue with that. However this is something that we can not circumvent. If we want to have a proxy object to an already existing class then we should have either an interface or we have to extend the original class, otherwise we just could not use the proxy object in place of the original one.

Advertisements

2 responses to “Creating a proxy object using cglib

  1. Pingback: Java Weekly 5/16: cglib, Hibernate performance, free ebook

  2. grimmeld March 15, 2016 at 1:33 pm

    What about constructors with parameters? Is there away to provide objects to inject into the super(…) call the proxy invokes during its constructor?

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: