看了tom老師講的深入分析spring源碼,講的挺好,做個小總結
代理模式的定義:
爲其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。
比如:
租房中介、火車票黃牛、媒人、經紀人、快遞
這些人和你之間的關係可以算作爲代理模式,在我需要租房、買票、拿快遞時我可以找一個這個中間人去替我辦這件事
代理模式需要滿足的特點:
1、執行者、被代理人
2、對於被代理人來說,這件事情是一定要做的,但是我自己又不想做或者沒有時間做,找代理。
3、需要獲取到被代理的人個人資料。
代理模式和裝飾模式區別:
代理模式關心的不是結果 是過程;裝飾模式關心的是最終結果
下面是一個小demo,創建了一個媒婆代理幫你找對象功能:
文件結構
Person類:
package spring;
public interface Person {
void findLove();
}
Zhansan類:
package spring;
public class Zhansan implements Person{
private String sex = "女";
private String name = "Zhansan";
@Override
public void findLove() {
System.out.println("我叫:"+this.name+" 性別:"+this.sex);
System.out.println("我要找高富帥");
}
}
Meipo類:
package spring;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Meipo implements InvocationHandler{
private Person target;
//獲取被代理人的個人資料
public Object getInstance(Person target) {
this.target = target;
Class clazz = target.getClass();
//生成代理對象:3個參數:ClassLoader類加載器 實現接口,代理人
System.out.println("被代理對象是:"+clazz);
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我是媒婆,準備介紹");
System.out.println("------------");
this.target.findLove();
System.out.println("------------");
return null;
}
}
測試類:
package spring;
public class TestFindLove {
public static void main(String[] args) {
Person obj = (Person) new Meipo().getInstance(new Zhansan());
System.out.println(obj.getClass());
obj.findLove();
/*原理:
* 1 拿到帶代理對象的引用,然後獲取它的接口
* 2 jdk代理重新生成一個類,同時實現我們給的代理對象所實現的接口
* 3 把被代理對象的引用也拿到了
* 4 重新動態生成一個class字節碼
* 5 編譯
*/
}
}
輸出結果:
可以看到,測試類中雖然new的是一個zhangsan類 但是obj.getClass()的輸出是代理類com.sun.proxy.$Proxy0