簡單理解靜態代理與動態代理(proxy方式)
阿新 • • 發佈:2020-12-30
技術標籤:Spring框架靜態代理動態代理proxy動態代理java
一:靜態代理 1:建立一個歌手介面,擁有三個抽象方法,(面談,唱歌,收錢)/**
* @Author sgl
* @Description 歌星介面
* @Date 2020/12/29 下午 15:23
**/
public interface Singer {
void confer(); //面談
void sing(); //唱歌
void collectMoney(); //收錢
}
2:建立歌手例項(陳奕迅),實現上面的歌手介面
3:建立歌手陳奕迅的代理類(經紀人),也實現歌手介面/** * @Description: 歌手陳奕迅 * @Author: sgl * @Date: 2020/12/29 0029 下午 15:30 */ public class Eason implements Singer { @Override public void confer() { System.out.println("Eason不親自談業務"); } @Override public void sing() { System.out.println("Eason開始唱歌..."); } @Override public void collectMoney() { System.out.println("Eason不親自收錢"); } }
有參構造傳入真正的歌手,然後重寫的唱歌方法讓歌手去作,代理類(經濟人)完成面談合同,和結束後的收錢方法 4:編寫測試類/** * @Description: 陳奕迅經紀人 * @Author: sgl * @Date: 2020/12/29 0029 下午 15:33 */ public class ProxyEason implements Singer { private Singer singer; public ProxyEason(Singer singer){ super(); this.singer = singer; } @Override public void confer() { //經紀人代談合同 System.out.println("經紀人談業務籤合同..."); } @Override public void sing() { //唱歌是歌手本人去唱 singer.sing(); } @Override public void collectMoney() { //經紀人代收錢 System.out.println("經紀人收錢..."); } }
public static void main(String[] args) {
Singer realSinger = new Eason();
Singer proxySinger = new ProxyEason(realSinger);
proxySinger.confer();
proxySinger.sing();
proxySinger.collectMoney();
}
執行結果:/**
* @Description: 陳奕迅動態代理物件
* @Author: sgl
* @Date: 2020/12/29 0029 下午 19:51
*/
public class EasonHandler implements InvocationHandler {
Singer singer;
public Object getInstance(Singer singer){
this.singer = singer;
/**
* 通過Proxy類的newProxyInstance方法建立代理物件,我們來看下方法中的引數
* 第一個引數:people.getClass().getClassLoader(),使用handler物件的classloader物件來載入我們的代理物件
* 第二個引數:people.getClass().getInterfaces(),這裡為代理類提供的介面是真實物件實現的介面,這樣代理物件就能像真實物件一樣呼叫介面中的所有方法
* 第三個引數:handler,我們將代理物件關聯到上面的InvocationHandler物件上
*/
return Proxy.newProxyInstance(singer.getClass().getClassLoader(),singer.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object object = null;
// 在代理真實物件前,我們可以做些自己的操作
System.out.println("動態代理經紀人幫忙面談");
if(method.getName().equals("sing")) {
object = method.invoke(singer, args);
}
// 在代理真是物件後,我們可以做些自己的操作
System.out.println("動態代理經紀人幫忙收錢");
return object;
}
}
可以看出,思路和靜態代理是一樣的,先通過構造方法把真正的物件傳進來,然後執行代理的部分是invoke方法中,
在該方法中,我們進行一次判斷,只有當需要唱歌的時候,我就呼叫剛剛傳進來的真實物件來唱,
其他事情由代理代替真實物件來做,這裡只用控制檯輸出來模擬一下。
編寫測試方法:
public static void main(String[] args) {
Singer realSinger = new Eason();
Singer proxySinger = (Singer) new EasonHandler().getInstance(realSinger);
proxySinger.sing();
}
執行結果:
由此可見,使用代理可以在執行某個邏輯的前後加上新的邏輯,這是很好的功能,實際中Spring的AOP用的就是這種技術。
但是:
proxy無法動態代理沒有介面的類,springaop的底層雖然也是使用動態代理,但不是proxy,而是
cglib
,cglib可以代理沒有介面的類
後面大家可以自己去了解下
cglib的方式是如何實現動態代理的。