代理


動態代理技術可以動態的生成一段內部有一個被擴展類引用的代碼,生成的類類似於用組合這種方式,並把它動態的編譯成class文件,然後裝載進jvm中執行。著名的框架Spring的核心技術之一aop就是使用的就是動態代理技術。

 Java中爲動態代理提供了支持,用到了類Proxy用於產生代理,還有一個接口InvocationHandler,用於在被代理的類的方法前後加入處理邏輯,這個接口內部有一個invoke方法,invoke接受三個參數,

代理Proxy 基本概念

安全、事物、日誌要貫穿到好多模塊中,就是交叉業務

AOP面向方面編程

目標:要使交叉業務模塊化,將切面代碼移動到原始方法的周圍
代理是實現AOP功能的核心和關鍵技術

JVM可以在運行期動態生成出類的字節碼,這種動態生成的類往往被用作代理類,即動態代理類

1JVM生成的動態類必須實現一個或多個接口,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;
	}
}

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