java動態代理(JDK和cglib)

java動態代理(JDK和cglib)

JAVA的動態代理 
代理模式 :
代理模式是常用的java設計模式,他的特徵是代理類與委託類有同樣的接口,代理類主要負責爲委託類預處理消息、過濾消息、把消息轉發給委託類,以及事後處理消息等。代理類與委託類之間通常會存在關聯關係,一個代理類的對象與一個委託類的對象關聯,代理類的對象本身並不真正實現服務,而是通過調用委託類的對象的相關方法,來提供特定的服務。 
按照代理的創建時期,代理類可以分爲兩種。 
靜態代理:由程序員創建或特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了。 
動態代理:在程序運行時,運用反射機制動態創建而成。


一、JDK動態代理:

直接使用JDK-API;

只能爲實現了接口的類創建代理對象(通過接口形式創建對象)。

/**

 * ①創建一個代理類JDKDynamicProxy實現InvocationHandler接口

 * ②實現接口中的invoke方法

 * ③在類中定義一個Object類型的屬性,用來傳遞被代理對象

 * ④提供一個帶有Object類型的構造器

 * ⑤創建一個方法getProxy返回一個對象,即爲被代理對象的代理對象

 */


程序清單:
1.TestInterface接口

package com.softeem.dynamicproxy;

public interface TestInterface {
	public void test01();
}

2.TestInterface實現接口

package com.softeem.dynamicproxy;

public class TestImplement implements TestInterface {
	@Override
	public void test01() {
		System.out.println("這是JDK動態代理測試方法");
	}
}

3.JDK動態代理

package com.softeem.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 直接使用JDK-API
 * 只能爲實現了接口的類創建代理對象(通過接口形式創建對象)
 * ①創建一個代理類JDKDynamicProxy實現InvocationHandler接口
 * ②實現接口中的invoke方法
 * ③在類中定義一個Object類型的屬性,用來傳遞被代理對象
 * ④提供一個帶有Object類型的構造器
 * ⑤創建一個方法getProxy返回一個對象,即爲被代理對象的代理對象
 */
public class JDKDynamicProxy implements InvocationHandler {

	private Object obj;
	
	public JDKDynamicProxy(Object obj) {
		this.obj = obj;
	}

	//獲取代理對象
	public Object getProxy(){
		Object proxyObj = null;
		proxyObj = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
		//要綁定接口(這是一個缺陷,cglib彌補了這一缺陷)
		return proxyObj;
	}


	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
			//tif.test01();第一個參數相當於tif,第二個參數相當於test01(),第三個參相當於參數
		
		System.out.println("-------");
		
		Object returnObj = method.invoke(obj, args);
		
		System.out.println("<><><><>");
		return returnObj;
	}

}

4.Test測試類

package com.softeem.dynamicproxy;

public class Test {
	
	public static void main(String[] args) {
		
		TestImplement ti = new TestImplement();
		
		//爲ti對象創建代理對象
		Object obj = new JDKDynamicProxy(ti).getProxy();//obj只存在於內存的對象
		
		System.out.println(obj.getClass());
		
		//因爲jdk動態代理是通過接口創建的代理對象
		TestInterface tif = (TestInterface) obj;
		//TestInterface tif2 = new TestImplement();
		//父類引用指向子類對象(多態),不能調用子類特有的方法,只能調用抽象方法中的類
		
		//通過代理對象調用方法時,實際上是調用類代理類中的invoke方法
		tif.test01();
	}
}


二、cglib動態代理

使用到類第三方jar包:CGLib.jar

不能爲final類創建代理對象(通過子類創建代理對象)

/**

 * ①創建一個代理類CGLibDynamicProxy實現MethodInterceptor接口

 * ②實現intercept方法

 * ③在類中定義一個Object類型的屬性,用來傳遞被代理對象

 * ④提供一個帶有Object類型的構造器

 * ⑤創建一個方法getProxy返回一個對象,即爲被代理對象的代理對象

 */

程序清單

1.cglib動態代理類CGLibDynamicProxy

package com.softeem.dynamicproxy;

import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

/**
 * 使用到類第三方jar包:CDLib.jar
 * 不能爲final類創建代理對象(通過子類創建代理對象)
 * ①創建一個代理類CGLibDynamicProxy實現MethodInterceptor接口
 * ②實現intercept方法
 * ③在類中定義一個Object類型的屬性,用來傳遞被代理對象
 * ④提供一個帶有Object類型的構造器
 * ⑤創建一個方法getProxy返回一個對象,即爲被代理對象的代理對象
 */
public class CGLibDynamicProxy implements MethodInterceptor {

	private Object obj;
	
	public CGLibDynamicProxy(Object obj) {
		this.obj = obj;
	}

	public Object getProxy(){
		//通過創建被代理對象的子類,來爲其創建代理對象
		Enhancer en = new Enhancer();
		en.setSuperclass(obj.getClass());
		en.setCallback(this);//回調
		
		return en.create();
	}

	/**
     * 在代理實例上處理方法調用並返回結果
     * 
     * @param proxy
     *            代理類
     * @param method
     *            被代理的方法
     * @param params
     *            該方法的參數數組
     * @param methodProxy
     * 			     代理的方法
     */
	@Override
	public Object intercept(Object arg0, Method method, Object[] arg2,
			MethodProxy arg3) throws Throwable {
		System.out.println("-------");
		Object returnObj = method.invoke(obj, arg2);
		System.out.println("<<><><><><>>");
		return returnObj;
	}
}

2.CGLibTest測試類

package com.softeem.dynamicproxy;

public class CGLibTest {
	
	public static void main(String[] args) {
		
		TestImplement ti = new TestImplement();
		
		CGLibDynamicProxy cgdp = new CGLibDynamicProxy(ti);
		//創建ti的代理對象obj
		Object obj = cgdp.getProxy();
		
		//通過創建被代理對象類的子類來創建的代理對象
		//所以可以講代理對象直接強轉成被代理對象的類型
		TestImplement t = (TestImplement) obj;
		
		t.test01();
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章