JDK的動態代理技術(JDK proxy)
我們先說怎麼實現JDK為我們提供的動態代理。(這篇文章目的是為Spring框架中的AOP思想提供技術支援)
0.用到反射包下的類,以及InvocationHandler介面。
需要寫自己的實現類。
問題1:為什麼一定要實現這個介面?
1.自定義工廠類,以JDkProxyFactor為自己的工廠類。
程式碼如下:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class JDkProxyFactory implements InvocationHandler{ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return null; } }
2.寫自己的業務邏輯。
關於方法的引數的說明:
proxy--為誰產生代理
Method--為哪個方法產生代理
Args--這個方法需要哪些引數
程式碼結構圖如下:
我就為Dog介面產生代理。
Dog介面有void bark()方法。
物件我不用他提供的Object proxy,我自己通過構造器注入一個。(沒有註釋請見諒)
private Object target; public JDKProxyFactory(Object target) { super(); this.target = target; }
--------------------------------------------------------------------------------------------關鍵的一步到了------------------------------------
真理總是很簡單,但人們卻常常很難發現它。
我要做什麼?為什麼一定要這樣做?為了AOP思想。
AOP思想是個神馬玩意兒?是不改原來的程式碼但是又可以新增程式碼的神奇技術。
因此,我們需要在原來的類的基礎上再克隆一個類,但是這個類寫我們要新增的程式碼,然後執行的是這個類而不是原來的類。
我要產生這樣一個位元組碼物件,更具體(在此文),我要產生Dog介面的物件,通過多型建立他子類哈士奇HashiQI的物件。
HaShiQi類:
package com.gzz.review;
public class HaShiQi implements Dog{
@Override
public void bark() {
System.out.println("主人給我骨頭");
}
public void play() {
System.out.println("主人陪我玩");
}
}
怎麼產生?
自己定義了一個方法用於得到我想要的類的物件。
提示需要一個classloader和一個介面和一個InvocationHandler。
通過讀取當前執行緒的類的上下文獲得classloader,讓它去載入這個類
程式碼如下:
Thread.currentThread().getContextClassLoader()
還需要一個介面
通過查API,我知道了,interfaces
- 代理類要實現的介面列表
還記得我們通過構造器傳過來的那個代理物件,那個物件在被建立的時候肯定是由多型建立了,其實那個物件是介面的實現類哈士奇物件。所以我們要得到那個介面,Dog。
同樣的,在反射包下提供了獲得介面的辦法。
程式碼如下:
target.getClass().getInterfaces()
還需要一個引數,InvocationHadler。直接傳this。因為這個JDkProxyFactory類實現了InvocationHadler介面。
我們就湊夠了這個引數。
這樣,就獲得了那個類的物件。
然後搞測試。
建立一個測試類,就叫TestDog吧。
程式碼如下:
package com.gzz.review;
public class TestDog {
public static void main(String[] args) {
Dog dog = new HaShiQi();
JDkProxyFactory jDkProxyFactory = new JDkProxyFactory(dog);
Dog hashiqi = (Dog) jDkProxyFactory.getProxy();
hashiqi.bark();
}
}
這樣我們就用JDK的方式實現了AOP思想。JDK動態代理技術的實現到此為止。
對了,還有問題一:我們可以寫自己的實現AOP的類,但必須實現InvocationHandler這個介面,就像寫Servlet就必須遵循sun公司幫我們制定好的xsd約束。這是一種規範,規範就必須遵循的。
值得說明,這種自己實現的技術有侷限,侷限是不能得到實現類的私有方法。本例中HaShiQi類的void play()方法就沒有拿到。