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;
}
}