摘要 之前老是聽說動態代理,一直沒有機會好好看過,現在就把動態代理的實現邏輯和用處整理一下。首先提兩個概念,委托類和代理類。委托類就是實際業務邏輯的處理者,代理類是處於請求發起者與委托類之間的角色,所有對委托類的請求都會經過代理類。就是委托類將請求處理委托給代理類,代理類可以起到方法攔截、功能增強的 ...
- 摘要
之前老是聽說動態代理,一直沒有機會好好看過,現在就把動態代理的實現邏輯和用處整理一下。
首先提兩個概念,委托類和代理類。委托類就是實際業務邏輯的處理者,代理類是處於請求發起者與委托類之間的角色,所有對委托類的請求都會經過代理類。
就是委托類將請求處理委托給代理類,代理類可以起到方法攔截、功能增強的作用。
實現動態代理的方式有很多,現在主流的主要jdk和cglib這兩個。下麵就用示例代碼說明下動態代理的過程,以及用動態代理實現攔截器。 - 用JDK實現動態代理
jdk實現動態代理的包是java.lang.reflect.*,jdk實現動態代理有限制,委托類必須要實現介面,所以先要創建一個介面
public interface MyInterface { //jdk public void tes1(); //cglib public void test2(String val); }
創建介面實現類public class MyTarget implements MyInterface { //jdk @Override public void tes1() { System.out.println("委托類業務處理!"); } //cglib @Override public void test2(String val) { System.out.println("業務處理結果:"+val); } }
動態代理邏輯代碼package proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class MyProxyTest implements InvocationHandler { //繼承InvocationHandler,攔截方法 private Object target=null; //構造函數 public MyProxyTest(Object target){ this.target = target ; } //獲取代理類的方法 public static Object getProxy(Object target){ //通過proxy創建代理類,需要三個參數,委托類的類載入器、委托類實現的介面、代理類 /** * 這是jdk的動態代理模式,必須要有介面 * proxy會把代理類掛載到所有介面下麵 * 如果委托類沒有實現任何介面會有問題,改用CGLIB的enhancer增強類做動態代理 */ return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),new MyProxyTest(target)); } //攔截方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("進入代理邏輯!"); System.out.println("代理類處理邏輯!"); Object result=null; result = method.invoke(target,args); System.out.println("委托類處理完後的邏輯!"); return result; } }
getProxy方法就是綁定委托類和代理類之間關係的方法,這裡綁定的代理類是this當前對象,也就是MyProxyTest 的實例對象,由於實現了InvocationHandler介面,所以在方法調用之前都會
通過invoke方法,在這裡就可以寫功能增強的代碼。method.invoke(target,args)是通過反射運行委托類的方法。
測試用例public class JunitTest { public static void main(String[] args) { /** * jdk動態代理 */ System.out.println("---------jdk動態代理--------"); //委托類 MyTarget target = new MyTarget(); //給委托類綁定代理類 MyInterface proxy = (MyInterface)MyProxyTest.getProxy(target); proxy.tes1(); } }
運行結果---------jdk動態代理-------- 進入代理邏輯! 代理類處理邏輯! 委托類業務處理! 委托類處理完後的邏輯!
我們發現進入了代理類的處理邏輯。
- CGLIB實現動態代理
CGLIB實現動態代理和JDK大同小異,不過CGLIB是通過創建增強類Enhancer,並且設置Enhancer的委托類和代理類來實現動態代理。CGLIB的委托類不需要實現介面。
動態代理邏輯
package proxy; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class MyCgLibProxy implements MethodInterceptor { public Object getProxy(Class target){ //創建增強類 Enhancer enhancer = new Enhancer(); //設置委托類 enhancer.setSuperclass(target); //設置代理類 enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("進入代理邏輯!"); System.out.println("代理類處理邏輯!"); Object result=null; result = methodProxy.invokeSuper(o,objects); System.out.println("委托類處理完後的邏輯!"); return result; } }
這裡的getProxy接收的不是委托類的實例對象而是委托類。代理類是this,MyCgLibProxy 的實例對象,由於實現了MethodInterceptor攔截器,所以方法調用都會經過intercept。
測試用例package proxy; public class JunitTest { public static void main(String[] args) { /** * cglib動態代理 */ System.out.println("---------cglib動態代理--------"); MyCgLibProxy cgLib = new MyCgLibProxy(); MyInterface cgLibProxy = (MyInterface)cgLib.getProxy(MyTarget.class); cgLibProxy.test2("cglib動態代理"); } }
運行結果
---------cglib動態代理-------- 進入代理邏輯! 代理類處理邏輯! 業務處理結果:cglib動態代理 委托類處理完後的邏輯!
簡單的實現動態代理的兩種方式就完成了,之後再講解攔截器和責任鏈模式
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10