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