反射與動态代理簡直是影視圈的神馬組合
Java可以在運作的時候知道對象的資訊,這主要展現在Java的兩個功能,RTTI和反射。
反射
上篇文章我們講了RTTI的一些特性,它可以确定運作時的對象類型,這個類是在編譯的時候是确定的,這樣才能通過編譯後的Class檔案來加載類對象。當我們在編譯時無法擷取類資訊的時候,就可以考慮使用反射,既然本地沒有Class檔案,可能就是通過網絡擷取Class檔案,這時候我們就可以使用反射來擷取類資訊。
JDK中有個java.lang.reflect反射包,裡面定義了反射用到的一些類,
代理
反射往往與動态代理相結合使用,所謂代理就是自己由于各種各樣的原因不好抛頭露面,有一個代理類來幫它完成一件事情,代理類往往在真正方法執行的前後添加邏輯。
下面我們舉個代理模式使用的例子來說明一些
靜态代理
定義一個接口:
interface Interface {
void doSomething();
}
定義真正的對象:
class RealObject implements Interface {
public void doSomething() {
System.out.println("簡單輸出");
}
}
定義代理類:
class SimpleProxy implements Interface {
private Interface proxied;
public SimpleProxy(Interface proxied) {
this.proxied = proxied;
}
public void doSomething() {
System.out.println("使用代理類");
proxied.doSomething();
}
}
使用:
new SimpleProxy(new RealObject()).doSomething();
這樣我們看一下代碼,,輸出結果如下會先輸出
使用代理類
,然後是
簡單輸出
這是靜态代理的實作,代理類需要我們定義,而動态代理就不一樣了。
動态代理
動态代理可以動态建立代理并動态調用需要代理的方法。
定義動态代理類,這裡我們使用實作InvocationHandler接口來,并重寫他的invoke()方法
動态代理類:
class DynamicProxyHandler implements InvocationHandler {
private Object proxied;
public DynamicProxyHandler(Object proxied) {
this.proxied = proxied;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理類: " + proxy.getClass() + ", 方法: " + method + ", 參數: " + args);
if(args != null)
for(Object arg : args)
System.out.println(" " + arg);
return method.invoke(proxied, args);
}
}
動态代理類的這一個invoke()方法的重寫就夠用了,當接口定義其他方法的時候,靜态代理類需要同時實作接口的其他方法,而動态代理類就不需要了,這就是它的優勢所在。
使用:
Interface proxy = (Interface)Proxy.newProxyInstance(
Interface.class.getClassLoader(),
new Class[]{ Interface.class },
new DynamicProxyHandler(new RealObject()));
proxy.doSomething();
運作結果:
代理類:class $Proxy0, 方法:public abstract void Interface.doSomething(),參數: null
這裡定義的動态代理類和靜态代理類差不多,但比靜态代理類稍微複雜一點。
總結
❤️ 感謝大家
- 歡迎關注我❤️,點贊👍🏻,評論🤤,轉發🙏
- 關注
,定期為你推送好文,還有群聊不定期抽獎活動,可以暢所欲言,與大神們一起交流,一起學習。周結論本人
- 有不當之處歡迎批評指正。