動態代理技術可以動態的生成一段內部有一個被擴展類引用的代碼,生成的類類似於用組合這種方式,並把它動態的編譯成class文件,然後裝載進jvm中執行。著名的框架Spring的核心技術之一aop就是使用的就是動態代理技術。
Java中爲動態代理提供了支持,用到了類Proxy用於產生代理,還有一個接口InvocationHandler,用於在被代理的類的方法前後加入處理邏輯,這個接口內部有一個invoke方法,invoke接受三個參數,
代理Proxy 基本概念
安全、事物、日誌要貫穿到好多模塊中,就是交叉業務
AOP面向方面編程
目標:要使交叉業務模塊化,將切面代碼移動到原始方法的周圍
代理是實現AOP功能的核心和關鍵技術
JVM可以在運行期動態生成出類的字節碼,這種動態生成的類往往被用作代理類,即動態代理類
1)JVM生成的動態類必須實現一個或多個接口,JVM生成的動態類只能用作具有相同接口的目標類的代
理
2)CGLIB庫可以動態生成一個類的子類一個類的子類也可以用作該類的代理。,如果要爲一個沒有實現
接口的類生成動態代理類,那麼可以使用CGLIB庫
代理方法在系統代碼位置
1)在調用模板方法之前
2)在調用模板方法之後
3)在調用模板方法之前後
4)在處理目標方法異常的catch塊中
二、創建代理
InvocationHandler接口
創建實現Collection接口的動態類和查看其名稱,分析Proxy.getProxyClass方法的各個參數
創建動態類的實例對象
1)用反射獲得構造方法
2)編寫一個簡單的InvocationHandler類
3)調用構造方法創建動態類的實例對象,並編寫的InvocationHandler類的實例對象穿進去
InvocationHandler的運行原理
創建某一接口 MyInterface的代理:
InvocationHandler handler = newMyInvocationHandler(...);
代理實例調用處理程序實現的接口,對代理實例調用方法時,將對方法調用進行編碼並將其指
派到它的調用處理程序的 invoke方法
Class proxyClass = Proxy.getProxyClass(MyInterface.class.getClassLoader(), new Class[] { MyInterface .class });
得到接口代理類的類加載器,要接口數組(因爲可能要加載的不是一個接口)
MyInterface myint = (MyInterface ) proxyClass.getConstructor(newClass[]{
InvocationHandler.class}).newInstance(new Object[] { handler });
創建代理的示例代碼:
package lianxi; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collection; public class proxytest { /** * @param args * @throws Exception * @throws SecurityException */ public static void main(String[] args) throws SecurityException, Exception { // TODO Auto-generated method stub Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class); Constructor[] Constructors = clazz.getConstructors(); for (Constructor constructor : Constructors) { StringBuilder sb = new StringBuilder(); sb.append("("); Class[] paramclazzs = constructor.getParameterTypes(); for (Class paramclazz : paramclazzs) { sb.append(paramclazz.getName()); sb.append(","); } if (paramclazzs.length != 0) sb.deleteCharAt(sb.length() - 1); sb.append(")"); System.out.println(constructor.getName() + sb.toString()); } class myInvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub return null; } } final ArrayList Target = new ArrayList(); Collection coll1 = (Collection) getProxy(Target); coll1.add("123"); coll1.add("456"); coll1.add("ert"); // System.out.println(coll1); System.out.println(Target); /* * System.out.println("*************************************"); Method[] * methods=clazz.getMethods(); for(Method method:methods){ StringBuilder * sb=new StringBuilder(); sb.append("("); Class[] * paramclazzs=method.getParameterTypes(); for(Class * paramclazz:paramclazzs){ sb.append(paramclazz.getName()); * sb.append(","); } if(paramclazzs.length!=0) * sb.deleteCharAt(sb.length()-1); sb.append(")"); * System.out.println(method.getName()+sb.toString()); } */ } private static Object getProxy(final Object Target) { Object coll1 = Proxy.newProxyInstance(Target.getClass() .getClassLoader(), Target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub long starttime = System.currentTimeMillis(); if ("123".equals(args[0])) args[0] = "hello"; Object obj = method.invoke(Target, args); System.out.println("args:::" + args); // System.out.println("proxy:::"+proxy); long endtime = System.currentTimeMillis(); System.out.println(method + "....runtime..." + (endtime - starttime)); return obj; } }); return coll1; } }