日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

動(dòng)態(tài)代理 Proxy InvocationHandler學(xué)習(xí)

系統(tǒng) 1824 0

?參考?http://www.iteye.com/topic/683613

參考?http://hi.baidu.com/malecu/item/9e0edc115cb597a1feded5a0

參考 http://www.educity.cn/wenda/360356.html

參考?http://langyu.iteye.com/blog/410071

?

      /**
 * 相親接口
 * 
 * @author zhengt
 * @time Jun 3, 2095 3:13:03 PM
 */
public interface XiangQinInterface {
	/**
	 * 相親方法
	 */
	public void xiangQin();
}
/**
 * 張三相親實(shí)現(xiàn)類
 * 
 * @author zhengt
 * @time Jun 3, 2095 3:14:48 PM
 */
public class ZhangSanXiangQinInterfaceImpl implements XiangQinInterface {
	public void xiangQin() {
		System.out.println("張三去相親,娶個(gè)漂亮老婆。");
	}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 相親可是一輩子的大事,相親前要準(zhǔn)備一下,打扮得帥氣些。
 * 
 * @author zhengt
 * @time Jun 3, 2095 3:15:48 PM
 */
public class ReadyInvocationHandler implements InvocationHandler {
	//相親接口的實(shí)現(xiàn)類,也就是張三相親類
	private Object zhangSan = null;

	public ReadyInvocationHandler(Object realSubject) {
		this.zhangSan = realSubject;
	}

	public Object invoke(Object proxy, Method m, Object[] args) {
		Object result = null;
		try {
			/**
			 * 動(dòng)態(tài)代理類$Proxy0調(diào)用xiangQin方法時(shí)會(huì)調(diào)用它自己的xiangQin方法,
			 * 而它自己的xiangQin方法里面調(diào)用的是super.h.invoke(this, , ),也就是父類Proxy的h的invoke方法,
			 * 也就是ReadyInvocationHandler類的invoke方法。
			 * 所以,invoke(Object proxy, Method m, Object[] args)種的proxy實(shí)際上就是動(dòng)態(tài)代理類$Proxy0,
			 * 如果你將其強(qiáng)轉(zhuǎn)成XiangQinInterface然后調(diào)用它的xiangQin方法,然后它就會(huì)調(diào)用super.h.invoke(this, , ),這樣就會(huì)死循環(huán)。
			 */
			/**
			 * 網(wǎng)上關(guān)于這里最多問題就是Object proxy放在這里用來做什么呢?這個(gè)我也不知道,
			 * 不過至少我們知道它到底是個(gè)什么東西,具體做什么用嘛就不得而知了
			 */
			System.out.println(proxy.getClass().getSimpleName());
			System.out.println("張三相親前,代理人給他打扮了打扮。");
			result = m.invoke(zhangSan, args);
		} catch (Exception ex) {
			System.exit(1);
		}
		return result;
	}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 張三來到了婚介所(相親現(xiàn)場(chǎng)),開始相親。
 * 
 * @author zhengt
 * @time Jun 3, 2095 3:17:16 PM
 */
public class HunJieSuo {
	public static void main(String args[]) {
		//先將張三相親這個(gè)相親的實(shí)現(xiàn)類實(shí)例化,也就是得到XiangQinInterface接口的一個(gè)實(shí)例對(duì)象
		XiangQinInterface zhangSan = new ZhangSanXiangQinInterfaceImpl();
		/**
		 * 得到ZhangSanXiangQinInterfaceImpl這個(gè)類的一個(gè)代理類,同時(shí)為代理類綁定了一個(gè)處理類ReadyInvocationHandler。
		 * 聽著很繞口,其實(shí)就是每次調(diào)用ZhangSanXiangQinInterfaceImpl這個(gè)子類的xiangQin方法時(shí),
		 * 不是zhangSan這個(gè)ZhangSanXiangQinInterfaceImpl類的實(shí)例去調(diào)用,
		 * 而是這個(gè)ZhangSanXiangQinInterfaceImpl的代理類ReadyInvocationHandler去調(diào)用它自己的invoke方法,
		 * 這個(gè)invoke方法里呢可以調(diào)用zhangSan這個(gè)實(shí)例的xiangQin方法
		 */
		/**
		 * 在java種怎樣實(shí)現(xiàn)動(dòng)態(tài)代理呢
		 * 第一步,我們要有一個(gè)接口,還要有一個(gè)接口的實(shí)現(xiàn)類,而這個(gè)實(shí)現(xiàn)類呢就是我們要代理的對(duì)象,
		 * 所謂代理呢也就是在調(diào)用實(shí)現(xiàn)類的方法時(shí),可以在方法執(zhí)行前后做額外的工作,這個(gè)就是代理。
		 * 第二步,我們要自己寫一個(gè)在要代理類的方法執(zhí)行時(shí),能夠做額外工作的類,而這個(gè)類必須繼承InvocationHandler接口,
		 * 為什么要繼承它呢?因?yàn)榇眍惖膶?shí)例在調(diào)用實(shí)現(xiàn)類的方法的時(shí)候,不會(huì)調(diào)真正的實(shí)現(xiàn)類的這個(gè)方法,
		 * 而是轉(zhuǎn)而調(diào)用這個(gè)類的invoke方法(繼承時(shí)必須實(shí)現(xiàn)的方法),在這個(gè)方法中你可以調(diào)用真正的實(shí)現(xiàn)類的這個(gè)方法。
		 * 第三步,在要用代理類的實(shí)例去調(diào)用實(shí)現(xiàn)類的方法的時(shí)候,寫出下面兩段代碼。
		 */
 // 獲得代理類($Proxy0 extends Proxy implements XiangQinInterface)的實(shí)例.
		XiangQinInterface proxy = (XiangQinInterface) Proxy.newProxyInstance(
				zhangSan.getClass().getClassLoader(),
				zhangSan.getClass().getInterfaces(),
				new ReadyInvocationHandler(zhangSan));
		proxy.xiangQin();
		/**
		 * 這里要解釋下中部那段長(zhǎng)長(zhǎng)的代碼的意思,以及具體做了哪些工作?
		 * 第一,根據(jù)zhangSan.getClass().getClassLoader()這個(gè)要代理類的類加載器和
		 * zhangSan.getClass().getInterfaces()要代理類所實(shí)現(xiàn)的所有的接口
		 * 作為參數(shù)調(diào)用Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces)
		 * 的方法返回代理類的java.lang.Class對(duì)象,也就是得到了java動(dòng)態(tài)生成的代理類$Proxy0的Class對(duì)象。
		 * 同時(shí),java還讓這個(gè)動(dòng)態(tài)生成的$Proxy0類實(shí)現(xiàn)了要代理類的實(shí)現(xiàn)的所有接口,并繼承了Proxy接口。
		 * 第二,實(shí)例化這個(gè)動(dòng)態(tài)生成的$Proxy0類的一個(gè)實(shí)例,實(shí)例化代理類的構(gòu)造函數(shù)為Proxy(InvocationHandler h),
		 * 也就是說要實(shí)例化這個(gè)動(dòng)態(tài)生成的$Proxy0類,必須給它一個(gè)InvocationHandler參數(shù),也就是我們自己實(shí)現(xiàn)的用來在代理類
		 * 方法執(zhí)行前后做額外工作的類ReadyInvocationHandler。
		 * 這段代碼Proxy.newProxyInstance(zhangSan.getClass().getClassLoader(),zhangSan.getClass().getInterfaces(),new ReadyInvocationHandler(zhangSan))
		 * 得到的其實(shí)是一個(gè)類名叫$Proxy0 extends Proxy implements XiangQinInterface的類。
		 * 第三,將這個(gè)$Proxy0類強(qiáng)制轉(zhuǎn)型成XiangQinInterface類型,調(diào)用xiangQin方法。
		 */
	}
}

    

?

備注:著重看“ // 獲得代理類($Proxy0 extends Proxy implements XiangQinInterface)的實(shí)例. ”這個(gè)注解 。?

? 動(dòng)態(tài)代理 Proxy InvocationHandler學(xué)習(xí)


?一.相關(guān)類及其方法:

java.lang.reflect.Proxy,

Proxy 提供用于創(chuàng)建動(dòng)態(tài)代理類和實(shí)例的靜態(tài)方法 .

newProxyInstance()

返回一個(gè)指定接口的代理類實(shí)例,該接口可以將方法調(diào)用指派到指定的調(diào)用處理程序

(詳見api文檔)

?

java.lang.reflect.InvocationHandler,

InvocationHandler 是代理實(shí)例的調(diào)用處理程序 實(shí)現(xiàn)的接口 。?

invoke()

在代理實(shí)例上處理方法調(diào)用并返回結(jié)果。在與方法關(guān)聯(lián)的代理實(shí)例上調(diào)用方法時(shí),將在調(diào)用處理程序上調(diào)用此方法。

?

創(chuàng)建某一接口 Foo 的代理:?

?

      InvocationHandler handler = new MyInvocationHandler(...);
Class proxyClass = Proxy.getProxyClass(
    Foo.class.getClassLoader(), new Class[] { Foo.class });
Foo f = (Foo) proxyClass.
    getConstructor(new Class[] { InvocationHandler.class }).
    newInstance(new Object[] { handler });
    

?

?

或使用以下更簡(jiǎn)單的方法:?

?

      Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
                                          new Class[] { Foo.class },
                                          handler);
    

?

?

四.機(jī)制分析:

Proxy.(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)做了以下幾件事.

(1)根據(jù)參數(shù)loader和interfaces調(diào)用方法 getProxyClass(loader, interfaces)創(chuàng)建代理類$Proxy.

$Proxy0類實(shí)現(xiàn)了interfaces的接口,并繼承了Proxy類.

?

(2)實(shí)例化$Proxy0并在構(gòu)造方法中把BusinessHandler傳過去,接著$Proxy0調(diào)用父類Proxy的構(gòu)造器,為h賦值,如下:

      class Proxy{
   InvocationHandler h=null;
   protected Proxy(InvocationHandler h) {
    this.h = h;
   }
   ...
}
    

?

?

下面是本例的$Proxy0類的源碼(好不容易才把它提出來):

?

      import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy implements 
      
        XiangQinInterface 
      
      
        {
      
      
private static Method m1;
private static Method m0;
private static Method m3;
private static Method m2;

static {
   try {
    m1 = Class.forName("java.lang.Object").getMethod("equals",
      new Class[] { Class.forName("java.lang.Object") });
    m0 = Class.forName("java.lang.Object").getMethod("hashCode",
      new Class[0]);
    m3 = Class.forName("com.ml.test.Manager").getMethod("modify",
      new Class[0]);
    m2 = Class.forName("java.lang.Object").getMethod("toString",
      new Class[0]);
   } catch (NoSuchMethodException nosuchmethodexception) {
    throw new NoSuchMethodError(nosuchmethodexception.getMessage());
   } catch (ClassNotFoundException classnotfoundexception) {
    throw new NoClassDefFoundError(classnotfoundexception.getMessage());
   }
}

public $Proxy0(InvocationHandler invocationhandler) {
   super(invocationhandler);
}
@Override
public final boolean equals(Object obj) {
   try {
    return ((Boolean) super.h.invoke(this, m1, new Object[] { obj }))
      .booleanValue();
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}
@Override
public final int hashCode() {
   try {
    return ((Integer) super.h.invoke(this, m0, null)).intValue();
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}
public final void modify() {
   try {
    super.h.invoke(this, m3, null);
    return;
   } catch (Error e) {
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}
@Override
public final String toString() {
   try {
    return (String) super.h.invoke(this, m2, null);
   } catch (Throwable throwable) {
    throw new UndeclaredThrowableException(throwable);
   }
}
}
    

?

?

?

接著把得到的$Proxy0實(shí)例強(qiáng)制轉(zhuǎn)換成XiangQinInterface?.

當(dāng)執(zhí)行proxy.xiangQin()方法時(shí),就調(diào)用了$Proxy0類中的xiangQin()方法.

在modify方法中,調(diào)用父類Proxy中的h的invoke()方法.

即InvocationHandler.invoke();?

動(dòng)態(tài)代理 Proxy InvocationHandler學(xué)習(xí)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 祁门县| 平邑县| 陵川县| 平南县| 清丰县| 海宁市| 曲周县| 中阳县| 白城市| 吴忠市| 汽车| 山阴县| 大连市| 甘孜| 石屏县| 布拖县| 孟津县| 台北市| 个旧市| 鹤岗市| 米林县| 福清市| 宁强县| 张家港市| 玉树县| 长泰县| 雷波县| 富蕴县| 南雄市| 高台县| 七台河市| 波密县| 米林县| 甘泉县| 时尚| 临潭县| 雅江县| 澄江县| 永昌县| 林芝县| 金阳县|