天天看點

第二章 Java基礎之GJLIB動态代理

CJLIB動态代理代碼實作

被代理類        

public class CameraSuoni {
	public void photo(){
		System.out.println("用索尼相機給美女照了一張相");
	}

}
           

代理對象和代理處理器類

import java.lang.reflect.Method;

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

public class CaremaCGLIBProxy implements MethodInterceptor{
	private Enhancer enhancer = new Enhancer();  
    public Object getProxy(Class cla){
    	//建立被代理類的子類位元組碼
    	enhancer.setSuperclass(cla);
    	//回調,回調intercept方法
    	enhancer.setCallback(this);
    	//根據位元組碼技術建立被代理類子類執行個體
    	Object obj = enhancer.create();
    	return obj;
    }
	public Object intercept(Object obj, Method method, Object[] arg2,
			MethodProxy arg3) throws Throwable {
		System.out.println("cglib動态代理----------------照相自帶ps美白功能");
		arg3.invokeSuper(obj, arg2);
		return null;
	}

}
           

測試類

public class CaremaCGLIBTest {
	public static void main(String[] args){
		//被代理對象
		CameraSuoni camera = new CameraSuoni();
		//代理處理器和代理對象建立類
		CaremaCGLIBProxy proxy  = new CaremaCGLIBProxy();
		//代理對象
		camera = (CameraSuoni) proxy.getProxy(camera.getClass());
		//已經帶有其他效果的代理對象方法
		camera.photo();
	}

}
           

輸出結果

cglib動态代理----------------照相自帶ps美白功能
用索尼相機給美女照了一張相
           

CGLIB包的底層是通過使用一個小而快的位元組碼處理架構ASM,來轉換位元組碼并生成新的類。

這裡看一下CGLIB和JDK實作的原理其實很像的,CaremaCGLIBProxy實作了MethodInterceptor,CaremaCGLIBProxy中的intercept方法和實作InvocationHandler的類中的invoke方法很相似,都是通過反射執行被代理對象的原方法。CaremaCGLIBProxy中的getProxy方法和Proxy的newInstatceProxy方法功能也是一樣的,都是建立代理對象。

CGLIB動态代理的原理

CGLIB動态代理就是将被代理對象和增強對象組合在一起生存一個代理對象的位元組碼檔案,再然後通過這個位元組碼檔案生成代理對象,代理對象将被代理對象作為父類進行繼承,在代理對象中重寫了父類的方法。我們在調用代理對象的方法時候,就會實作增強和父類方法中所實作的效果。

CGLIB動态代理和JDK動态代理的不同和相同點

相同點

CGLIB和JDK都是通過位元組碼檔案生成代理執行個體,不需要建立代理對象源檔案。

兩者的具體實作方式也是很相似的,JDK代理有一個代理處理器實作了InvokeHandler接口,重寫invoke方法,在invoke方法中通過反射調用目标對象的方法。

GLIB代理是有一個方法攔截處理器實作了MethodInterceptor,重寫intercept方法,在intercept方法中利用反射調用目标對象的方法。

JDK代理是通過Proxy來生成代理對象,CLIB代理是通過Enhancer來生成動态代理對象

不通點

JDK中的被代理對象必須實作接口,代理對象和被代理對象實作的是同一個接口

CGLIB被代理對象可以不實作接口,代理對象繼承了被代理對象,是以CGLIB中的被代理對象不能有final修飾,代理對象調用的方法在被代理對象中也不能是fianl