1. 程式人生 > >java類載入器和動態代理

java類載入器和動態代理

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.Collection;
public class ProxyTest {
	public static void main(String[] args) throws Exception 
	{
		//Proxy的靜態方法getProxyClass獲取動態代理Class物件
		Class clazzProxy1=Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
		System.out.println(clazzProxy1.getName());
		//列出動態代理類的所有構造方法和引數簽名
		System.out.println(".....begin constructors list.....");
		Constructor[] constructors=clazzProxy1.getConstructors();
		for(Constructor constructor:constructors){
			String name=constructor.getName();
			StringBuilder sbu=new StringBuilder(name);
			sbu.append("(");
			Class[] clazzParams=constructor.getParameterTypes();
			for(Class clazzParam:clazzParams){
				sbu.append(clazzParam.getName()).append(",");
			}
			if(clazzParams!=null&&clazzParams.length!=0){
				sbu.deleteCharAt(sbu.length()-1);
			}
			sbu.append(")");
			System.out.println(sbu.toString());
		}
		//列出動態代理類的所有方法和引數簽名
		System.out.println(".....begin Methods list.....");
		Method[] methods=clazzProxy1.getMethods();
		for(Method method:methods){
			String name=method.getName();
			StringBuilder sbu=new StringBuilder(name);
			sbu.append("(");
			Class[] clazzParams=method.getParameterTypes();
			for(Class clazzParam:clazzParams){
				sbu.append(clazzParam.getName()).append(",");
			}
			if(clazzParams!=null&&clazzParams.length!=0){
				sbu.deleteCharAt(sbu.length()-1);
			}
			sbu.append(")");
			System.out.println(sbu.toString());
		}
		//建立動態代理類的例項物件
		//方式一:
		System.out.println(".....begin create instance object.....");
		Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);		
		class MyInvocationHandler1 implements InvocationHandler{
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				// TODO Auto-generated method stub
				return null;
			}
		}
		Collection proxy1=(Collection)constructor.newInstance(new MyInvocationHandler1());
		//代理類中從java.lang.Object類繼承的方法中,只有hashCode(),equals()和toString()方法會委託給Invocationhandler執行,執行時會執行InvocationHandler中的invoke()方法,其它從Object類中繼承的方法不會委託給Invocationhandle.
		System.out.println(proxy1);
		//沒有返回值的clear()方法可正常執行,因為InvocationHandler返回null,與clear()原先的返回型別void不矛盾。
		proxy1.clear();
		//執行時報錯,因為size()應該返回整數值,但現在委託給InvocationHandler後返回的是null,不匹配
		//System.out.println(proxy1.size());
		//方式二:匿名內部類方式
		Collection proxy2=(Collection)constructor.newInstance(new InvocationHandler(){
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				return null;
			}			
		});
		//方式三:直接使用Proxy的靜態方法newProxyInstance()方法
		Collection proxy3=(Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(), 
				new Class[]{Collection.class}, 
				new InvocationHandler(){
			        //建立目標類例項物件
					ArrayList target=new ArrayList();
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						//在目標類的基礎功能前進行功能擴充套件
						long beginTime=System.currentTimeMillis();
						//執行目標物件的method方法
						Object retVal=method.invoke(target, args);
						//在目標類的基礎功能後進行功能擴充套件
						long endTime=System.currentTimeMillis();
						System.out.println(method.getName()+" running time of "+(endTime-beginTime));
						return retVal;
					}			
		        }
		);
		//每次呼叫proxy3的add方法,其實都是執行InvocationHandler子類中的invoke()方法,將proxy3賦給invoke()方法的第一個引數,add代表的Method物件賦經第從此引數,add()的引數"sss"賦給invoke()的第3個引數args
		proxy3.add("sss");
		proxy3.add("wtet");
		Object retVal=(Object)proxy3.add("gfdh");
		System.out.println(retVal);
		System.out.println(proxy3.size());
		//動態代理類的getClass()方法不會委託給InvocationHandler執行,所以仍列印是的$Proxy0,而不是ArrayList
		System.out.println(proxy3.getClass().getName());
	}
}
/*執行結果:
com.sun.proxy.$Proxy0
.....begin constructors list.....
com.sun.proxy.$Proxy0(java.lang.reflect.InvocationHandler)
.....begin Methods list.....
add(java.lang.Object)
remove(java.lang.Object)
equals(java.lang.Object)
toString()
hashCode()
clear()
contains(java.lang.Object)
isEmpty()
size()
toArray()
toArray([Ljava.lang.Object;)
addAll(java.util.Collection)
iterator()
containsAll(java.util.Collection)
removeAll(java.util.Collection)
retainAll(java.util.Collection)
isProxyClass(java.lang.Class)
getInvocationHandler(java.lang.Object)
getProxyClass(java.lang.ClassLoader,[Ljava.lang.Class;)
newProxyInstance(java.lang.ClassLoader,[Ljava.lang.Class;,java.lang.reflect.InvocationHandler)
wait(long,int)
wait(long)
wait()
getClass()
notify()
notifyAll()
.....begin create instance object.....
null
add running time of 1
add running time of 0
add running time of 0
true
size running time of 0
3
com.sun.proxy.$Proxy0
*/