前幾天看到java的動態代理機制,不知道是啥玩意,然後看了看。死活不知道
nvoke(Object proxy, Method m, Object[] args)種的proxy是個什麼東西,放在這裏有什麼用?於是網上到處搜刮,把自己的理解寫了寫。
- /**
- * 相親接口
- *
- * @author zhengt
- * @time Jun 3, 2095 3:13:03 PM
- */
- public interface XiangQinInterface {
- /**
- * 相親方法
- */
- public void xiangQin();
- }
- /**
- * 張三相親實現類
- *
- * @author zhengt
- * @time Jun 3, 2095 3:14:48 PM
- */
- public class ZhangSanXiangQinInterfaceImplimplements XiangQinInterface {
- public void xiangQin() {
- System.out.println("張三去相親,娶個漂亮老婆。");
- }
- }
- import java.lang.reflect.InvocationHandler;
- import java.lang.reflect.Method;
- /**
- * 相親可是一輩子的大事,相親前要準備一下,打扮得帥氣些。
- *
- * @author zhengt
- * @time Jun 3, 2095 3:15:48 PM
- */
- public class ReadyInvocationHandlerimplements InvocationHandler {
- //相親接口的實現類,也就是張三相親類
- private Object zhangSan = null;
- public ReadyInvocationHandler(Object realSubject) {
- this.zhangSan = realSubject;
- }
- public Object invoke(Object proxy, Method m, Object[] args) {
- Object result = null;
- try {
- /**
- * 動態代理類$Proxy0調用xiangQin方法時會調用它自己的xiangQin方法,
- * 而它自己的xiangQin方法裏面調用的是super.h.invoke(this, , ),也就是父類Proxy的h的invoke方法,
- * 也就是ReadyInvocationHandler類的invoke方法。
- * 所以,invoke(Object proxy, Method m, Object[] args)種的proxy實際上就是動態代理類$Proxy0,
- * 如果你將其強轉成XiangQinInterface然後調用它的xiangQin方法,然後它就會調用super.h.invoke(this, , ),這樣就會死循環。
- */
- /**
- * 網上關於這裏最多問題就是Object proxy放在這裏用來做什麼呢?這個我也不知道,
- * 不過至少我們知道它到底是個什麼東西,具體做什麼用嘛就不得而知了
- */
- 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;
- /**
- * 張三來到了婚介所(相親現場),開始相親。
- *
- * @author zhengt
- * @time Jun 3, 2095 3:17:16 PM
- */
- public class HunJieSuo {
- public staticvoid main(String args[]) {
- //先將張三相親這個相親的實現類實例化,也就是得到XiangQinInterface接口的一個實例對象
- XiangQinInterface zhangSan = new ZhangSanXiangQinInterfaceImpl();
- /**
- * 得到ZhangSanXiangQinInterfaceImpl這個類的一個代理類,同時爲代理類綁定了一個處理類ReadyInvocationHandler。
- * 聽着很繞口,其實就是每次調用ZhangSanXiangQinInterfaceImpl這個子類的xiangQin方法時,
- * 不是zhangSan這個ZhangSanXiangQinInterfaceImpl類的實例去調用,
- * 而是這個ZhangSanXiangQinInterfaceImpl的代理類ReadyInvocationHandler去調用它自己的invoke方法,
- * 這個invoke方法裏呢可以調用zhangSan這個實例的xiangQin方法
- */
- /**
- * 在java種怎樣實現動態代理呢
- * 第一步,我們要有一個接口,還要有一個接口的實現類,而這個實現類呢就是我們要代理的對象,
- * 所謂代理呢也就是在調用實現類的方法時,可以在方法執行前後做額外的工作,這個就是代理。
- * 第二步,我們要自己寫一個在要代理類的方法執行時,能夠做額外工作的類,而這個類必須繼承InvocationHandler接口,
- * 爲什麼要繼承它呢?因爲代理類的實例在調用實現類的方法的時候,不會調真正的實現類的這個方法,
- * 而是轉而調用這個類的invoke方法(繼承時必須實現的方法),在這個方法中你可以調用真正的實現類的這個方法。
- * 第三步,在要用代理類的實例去調用實現類的方法的時候,寫出下面兩段代碼。
- */
- XiangQinInterface proxy = (XiangQinInterface) Proxy.newProxyInstance(
- zhangSan.getClass().getClassLoader(),
- zhangSan.getClass().getInterfaces(),
- new ReadyInvocationHandler(zhangSan));
- proxy.xiangQin();
- /**
- * 這裏要解釋下中部那段長長的代碼的意思,以及具體做了哪些工作?
- * 第一,根據zhangSan.getClass().getClassLoader()這個要代理類的類加載器和
- * zhangSan.getClass().getInterfaces()要代理類所實現的所有的接口
- * 作爲參數調用Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces)
- * 的方法返回代理類的java.lang.Class對象,也就是得到了java動態生成的代理類$Proxy0的Class對象。
- * 同時,java還讓這個動態生成的$Proxy0類實現了要代理類的實現的所有接口,並繼承了Proxy接口。
- * 第二,實例化這個動態生成的$Proxy0類的一個實例,實例化代理類的構造函數爲Proxy(InvocationHandler h),
- * 也就是說要實例化這個動態生成的$Proxy0類,必須給它一個InvocationHandler參數,也就是我們自己實現的用來在代理類
- * 方法執行前後做額外工作的類ReadyInvocationHandler。
- * 這段代碼Proxy.newProxyInstance(zhangSan.getClass().getClassLoader(),zhangSan.getClass().getInterfaces(),new ReadyInvocationHandler(zhangSan))
- * 得到的其實是一個類名叫$Proxy0 extends Proxy implements XiangQinInterface的類。
- * 第三,將這個$Proxy0類強制轉型成XiangQinInterface類型,調用xiangQin方法。
- */
- }
- }
/**
* 相親接口
*
* @author zhengt
* @time Jun 3, 2095 3:13:03 PM
*/
public interface XiangQinInterface {
/**
* 相親方法
*/
public void xiangQin();
}
/**
* 張三相親實現類
*
* @author zhengt
* @time Jun 3, 2095 3:14:48 PM
*/
public class ZhangSanXiangQinInterfaceImpl implements XiangQinInterface {
public void xiangQin() {
System.out.println("張三去相親,娶個漂亮老婆。");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 相親可是一輩子的大事,相親前要準備一下,打扮得帥氣些。
*
* @author zhengt
* @time Jun 3, 2095 3:15:48 PM
*/
public class ReadyInvocationHandler implements InvocationHandler {
//相親接口的實現類,也就是張三相親類
private Object zhangSan = null;
public ReadyInvocationHandler(Object realSubject) {
this.zhangSan = realSubject;
}
public Object invoke(Object proxy, Method m, Object[] args) {
Object result = null;
try {
/**
* 動態代理類$Proxy0調用xiangQin方法時會調用它自己的xiangQin方法,
* 而它自己的xiangQin方法裏面調用的是super.h.invoke(this, , ),也就是父類Proxy的h的invoke方法,
* 也就是ReadyInvocationHandler類的invoke方法。
* 所以,invoke(Object proxy, Method m, Object[] args)種的proxy實際上就是動態代理類$Proxy0,
* 如果你將其強轉成XiangQinInterface然後調用它的xiangQin方法,然後它就會調用super.h.invoke(this, , ),這樣就會死循環。
*/
/**
* 網上關於這裏最多問題就是Object proxy放在這裏用來做什麼呢?這個我也不知道,
* 不過至少我們知道它到底是個什麼東西,具體做什麼用嘛就不得而知了
*/
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;
/**
* 張三來到了婚介所(相親現場),開始相親。
*
* @author zhengt
* @time Jun 3, 2095 3:17:16 PM
*/
public class HunJieSuo {
public static void main(String args[]) {
//先將張三相親這個相親的實現類實例化,也就是得到XiangQinInterface接口的一個實例對象
XiangQinInterface zhangSan = new ZhangSanXiangQinInterfaceImpl();
/**
* 得到ZhangSanXiangQinInterfaceImpl這個類的一個代理類,同時爲代理類綁定了一個處理類ReadyInvocationHandler。
* 聽着很繞口,其實就是每次調用ZhangSanXiangQinInterfaceImpl這個子類的xiangQin方法時,
* 不是zhangSan這個ZhangSanXiangQinInterfaceImpl類的實例去調用,
* 而是這個ZhangSanXiangQinInterfaceImpl的代理類ReadyInvocationHandler去調用它自己的invoke方法,
* 這個invoke方法裏呢可以調用zhangSan這個實例的xiangQin方法
*/
/**
* 在java種怎樣實現動態代理呢
* 第一步,我們要有一個接口,還要有一個接口的實現類,而這個實現類呢就是我們要代理的對象,
* 所謂代理呢也就是在調用實現類的方法時,可以在方法執行前後做額外的工作,這個就是代理。
* 第二步,我們要自己寫一個在要代理類的方法執行時,能夠做額外工作的類,而這個類必須繼承InvocationHandler接口,
* 爲什麼要繼承它呢?因爲代理類的實例在調用實現類的方法的時候,不會調真正的實現類的這個方法,
* 而是轉而調用這個類的invoke方法(繼承時必須實現的方法),在這個方法中你可以調用真正的實現類的這個方法。
* 第三步,在要用代理類的實例去調用實現類的方法的時候,寫出下面兩段代碼。
*/
XiangQinInterface proxy = (XiangQinInterface) Proxy.newProxyInstance(
zhangSan.getClass().getClassLoader(),
zhangSan.getClass().getInterfaces(),
new ReadyInvocationHandler(zhangSan));
proxy.xiangQin();
/**
* 這裏要解釋下中部那段長長的代碼的意思,以及具體做了哪些工作?
* 第一,根據zhangSan.getClass().getClassLoader()這個要代理類的類加載器和
* zhangSan.getClass().getInterfaces()要代理類所實現的所有的接口
* 作爲參數調用Proxy.getProxyClass(ClassLoader loader, Class<?>... interfaces)
* 的方法返回代理類的java.lang.Class對象,也就是得到了java動態生成的代理類$Proxy0的Class對象。
* 同時,java還讓這個動態生成的$Proxy0類實現了要代理類的實現的所有接口,並繼承了Proxy接口。
* 第二,實例化這個動態生成的$Proxy0類的一個實例,實例化代理類的構造函數爲Proxy(InvocationHandler h),
* 也就是說要實例化這個動態生成的$Proxy0類,必須給它一個InvocationHandler參數,也就是我們自己實現的用來在代理類
* 方法執行前後做額外工作的類ReadyInvocationHandler。
* 這段代碼Proxy.newProxyInstance(zhangSan.getClass().getClassLoader(),zhangSan.getClass().getInterfaces(),new ReadyInvocationHandler(zhangSan))
* 得到的其實是一個類名叫$Proxy0 extends Proxy implements XiangQinInterface的類。
* 第三,將這個$Proxy0類強制轉型成XiangQinInterface類型,調用xiangQin方法。
*/
}
}
網上看到一個牛人讀過這個動態代理的源代碼,希望對網友們有幫助。
java 動態代理深度學習(Proxy,InvocationHandler),含$Proxy0源碼
java 動態代理深度學習,
一.相關類及其方法:
java.lang.reflect.Proxy,
Proxy 提供用於創建動態代理類和實例的靜態方法.
newProxyInstance()
返回一個指定接口的代理類實例,該接口可以將方法調用指派到指定的調用處理程序
(詳見api文檔)
java.lang.reflect.InvocationHandler,
InvocationHandler 是代理實例的調用處理程序 實現的接口。
invoke()
在代理實例上處理方法調用並返回結果。在與方法關聯的代理實例上調用方法時,將在調用處理程序上調用此方法。
(詳見api文檔)
二.源代碼:
被代理對象的接口及實現類:
package com.ml.test;
public interface Manager {
public void modify();
}
package com.ml.test;
public class ManagerImpl implements Manager {
@Override
public void modify() {
System.out.println("*******modify()方法被調用");
}
}
業務代理類:
package com.ml.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class BusinessHandler implements InvocationHandler {
private Object object = null;
public BusinessHandler(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("do something before method");
Object ret = method.invoke(this.object, args);
System.out.println("do something after method");
return ret;
}
}
客戶端類:
package com.ml.test;
import java.lang.reflect.Proxy;
public class Client {
public static void main(String[] args) {
// 元對象(被代理對象)
ManagerImpl managerImpl = new ManagerImpl();
// 業務代理類
BusinessHandler securityHandler = new BusinessHandler(managerImpl);
// 獲得代理類($Proxy0 extends Proxy implements Manager)的實例.
Manager managerProxy = (Manager) Proxy.newProxyInstance(managerImpl
.getClass().getClassLoader(), managerImpl.getClass()
.getInterfaces(), securityHandler);
managerProxy.modify();
}
}
三.執行結果:
do something before method
*******modify()方法被調用
do something after method
四.機制分析:
Proxy.(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)做了以下幾件事.
(1)根據參數loader和interfaces調用方法 getProxyClass(loader, interfaces)創建代理類$Proxy.
$Proxy0類實現了interfaces的接口,並繼承了Proxy類.
(2)實例化$Proxy0並在構造方法中把BusinessHandler傳過去,接着$Proxy0調用父類Proxy的構造器,爲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 Manager {
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實例強制轉換成Manager.
當執行managerProxy.modify()方法時,就調用了$Proxy0類中的modify()方法.
在modify方法中,調用父類Proxy中的h的invoke()方法.
即InvocationHandler.invoke();