CGLIB是一個強大的高性能的代碼生成包。它被許多AOP的框架(例如Spring AOP)使用,爲他們提供方法的interception(攔截)。Hibernate也使用CGLIB來代理單端single-ended(多對一和一對一)關聯。EasyMock通過使用模仿(moke)對象來測試java代碼的包。它們都通過使用CGLIB來爲那些沒有接口的類創建模仿(moke)對象。
CGLIB包的底層是通過使用一個小而快的字節碼處理框架ASM,來轉換字節碼並生成新的類。不鼓勵直接使用ASM,因爲它要求你必須對JVM內部結構包括class文件的格式和指令集都很熟悉。
以下爲模擬案例,在使用CGLIB時需引入cglib-nodep-2.1_3.jar包
1.定義一個HelloWorld類,注意此處是個類,而不是接口
package com.lvyuanj.test;
/**
* 定義一個HelloWorld類
*
* @author lvyuanj
*
*/
public class HelloWorld {
public void sayHelloWorld() {
System.out.println("HelloWorld!");
}
}
2.CglibProxy類
package com.lvyuanj.test;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 通過Cglib實現在方法調用前後向控制檯輸出兩句字符串
*
* @author lvyuanj
*
*/
public class CglibProxy implements MethodInterceptor {
//要代理的原始對象
private Object obj;
public Object createProxy(Object target) {
this.obj = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.obj.getClass());// 設置代理目標
enhancer.setCallback(this);// 設置回調
enhancer.setClassLoader(target.getClass().getClassLoader());
return enhancer.create();
}
/**
* 在代理實例上處理方法調用並返回結果
*
* @param proxy
* 代理類
* @param method
* 被代理的方法
* @param params
* 該方法的參數數組
* @param methodProxy
*/
public Object intercept(Object proxy, Method method, Object[] params,
MethodProxy methodProxy) throws Throwable {
Object result = null;
// 調用之前
doBefore();
// 調用原始對象的方法
result = methodProxy.invokeSuper(proxy, params);
// 調用之後
doAfter();
return result;
}
private void doBefore() {
System.out.println("before method invoke");
}
private void doAfter() {
System.out.println("after method invoke");
}
}
3.測試類
package com.lvyuanj.test;
public class HelloWorldTest {
public static void main(String[] args) {
HelloWorld helloWorld=new HelloWorld();
CglibProxy cglibProxy=new CglibProxy();
HelloWorld hw=(HelloWorld)cglibProxy.createProxy(helloWorld);
hw.sayHelloWorld();
}
}
4.運行結果爲:
before method invoke
HelloWorld!
after method invoke