Tuesday, 5 July 2011

what is cglib?

cglib is a powerful, high performance and quality Code Generation Library, It is used to extend JAVA classes and implements interfaces at runtime.

In order to create a working example we'll need to open a regular java project and add two jars as a dependency (the latest versions available at the moment):

- cglib-2.2.jar
- asm-all-3.2.jar


We will 'proxify' the mock Executable class and add transaction management to it.

public class Executable {
public void executeMe() {
        System.out.println("execution begins");
        // real time operation here       
      System.out.println("execution ends");    
    }
}

We'll create a class that adds the 'transactions'. This class will be used by CGLIB to proxify the executable class, so it should implement net.sf.cglib.proxy.MethodInterceptor

The class looks like this:
import net.sf.cglib.proxy.MethodInterceptor;   

import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class MyInterceptor implements MethodInterceptor {
    // the real object     
    private Object realObj;
   // constructor - the supplied parameter is an
    // object whose proxy we would like to create    
    public MyInterceptor(Object obj) {
        this.realObj = obj;
    }
    // this method will be called each time     
    // when the object proxy calls any of its methods    
    public Object intercept(Object o,
                            Method method,
                            Object[] objects,
                            MethodProxy methodProxy) throws Throwable {
        // just print that we're about to execute the method        
        System.out.println("Before");        
        // Begin Transaction        
       System.out.println("transaction begins");        
        // invoke the method on the real object with the given params        
        Object res = method.invoke(realObj, objects);
        // print that the method is finished        
        System.out.println("After");
        // Commit Transaction
        System.out.println("Transaction commit”);
        // return the result        
        return res;
    }

}

The last class is the main class. Here we will actually create the proxy so here we'll see some CGLIB related code:


import net.sf.cglib.proxy.Enhancer;

public class Main {
    public static void main(String[] args) {
        // 1. create the 'real' object
        Executable exe = new  Executable ();
        // 2. create the proxy
        Executable proxifiedExecutable = createProxy(exe);
        // 3. execute the proxy - as we see it has the same API as the real object
        proxifiedExecutable.executeMe();
    }
    // given the obj, creates its proxy
    // the method is generified - just to avoid downcasting...
    public static T createProxy(T obj) {
        // this is the main cglib api entry-point
        // this object will 'enhance' (in terms of CGLIB) with new capabilities
        // one can treat this class as a 'Builder' for the dynamic proxy
        Enhancer e = new Enhancer();
        // the class will extend from the real class
        e.setSuperclass(obj.getClass());
        // we have to declare the interceptor  - the class whose 'intercept'
        // will be called when any method of the proxified object is called.
        e.setCallback(new MyInterceptor(obj));
        // now the enhancer is configured and we'll create the proxified object
        T proxifiedObj = (T) e.create();
        // the object is ready to be used - return it
        return proxifiedObj;
    }
}

1 comment:

  1. Well I did not understand a few things in this example. Please explain if you can:

    1. What do you mean by // real time operation here. I mean what do I suppose to write here?
    2. When I tried to use e.setCallback(new MyInterceptor(obj)); it showed Error and gave an option to cast it in Callback

    3. What is the missing type "T". Imean What do I suppose to replace it with.

    ReplyDelete