1、什麼是代理模式?
@百度:
即Proxy Pattern,23種常用的面向對象軟件的設計模式之一。(設計模式的說法源自《設計模式》一書,原名《Design Patterns: Elements of Reusable Object-Oriented Software》。1995年出版,出版社:Addison Wesly Longman.Inc。該書提出了23種基本設計模式,第一次將設計模式提升到理論高度,並將之規範化。)
代理模式的定義:爲其他對象提供一種代理以控制對這個對象的訪問。在某些情況下,一個對象不適合或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。
@個人:
代理模式是屬於常見的23中設計模式之一。
代理模式的定義:代理模式是在某些對象不能創建或者不能複合條件的引用一個對象,從而產生的代理對象(也就是代理模式)。
例如:
我編寫一個接口,但是我沒編寫它的實現類,那麼我怎麼去成功的實現以及使用這個方法呢?
如下列代碼:
package com.nyhs.dao;
public interface Demo {
void add();
}
這是demo中的一個add也就是一個添加方法。
但是我沒有這個類的實現類,那麼我該怎麼實現這個方法並且成功運行我想要運行的代碼呢?
這時候代理模式就產生了。
2、代理模式
代理模式分爲一下幾種
-
靜態代理模式
- 動態代理模式
3、靜態代理模式
例:
package com.nyhs.demo.proxy;
import com.nyhs.demo.demo;
public class Proxy implements demo {
public void add() {
System.out.println("代理對象中");
}
}
如上面代理所示這便是靜態代理對象,(個人感覺這和實現類沒什麼區別),但的的確確的代理是通過這種形式的方式去實現的,請看這段代碼
package com.nyhs.demo.proxy;
import com.nyhs.demo.demo;
public class Proxy implements demo {
// 實際代理對象
private Object proxyObject;
public Proxy(Object proxyObject) {
this.proxyObject = proxyObject;
}
public void add() {
System.out.println("代理對象中");
}
}
這是否就像是SpringAop中呢?(這時候可能還不會感覺這代碼哪裏就像是代理模式,那我改造一下)
package com.nyhs.demo.proxy;
import java.lang.reflect.Method;
import com.nyhs.demo.demo;
public class Proxy implements demo {
// 實際代理對象子類
private Object proxyObject;
public Proxy(Object proxyObject) {
this.proxyObject = proxyObject;
}
public void add() {
System.out.println("代理對象中");
// 通過反射獲取對象
Class classz = proxyObject.getClass();
try {
// 通過反射獲取add方法
Method method = classz.getDeclaredMethod("add");
// 執行代碼前
System.out.println("執行前,前置通知");
// 執行傳入對象的add方法
method.invoke(proxyObject, method);
// 執行代碼後
System.out.println("執行後,後置通知");
} catch (Exception e) {
e.printStackTrace();
}
}
}
此時該代理類就與AOP差不多了
靜態代理優點以及缺點
- 優點:
可擴展性強
代碼簡潔不影響源代碼的使用
2.缺點
每一次代理都需要產生一個代理類
重複的代理類使得代碼效率過低
4、動態代理模式
1、JDK動態代理
2、CGLIB動態代理
5、這兩種動態代理模式有什麼區別呢?
- JDK動態代理是基於反射來實現的,也就是上面的例子
例:
package com.nyhs.test;
import java.lang.reflect.Proxy;
import com.nyhs.demo.Demo;
import com.nyhs.demo.proxy.ProxyDemo;
public class Test {
public static void main(String[] args) {
// 對應參數爲:1、類加載器,爲了實時能夠獲取動態代理內容2、需要代理的類接口,實際代理方法
Demo demo = (Demo) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[] { Demo.class },
new ProxyDemo(Demo.class));
}
}
package com.nyhs.demo.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class ProxyDemo implements InvocationHandler {
// 代理對象
private Object object;
public ProxyDemo(Object object) {
this.object = object;
}
//參數爲:1、實際代理對象2、代理對象方法3、調用所代理的方法傳入的參數
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
}
這裏實際代理類是需要繼承InvocationHandler類,並且實現invoke方法。
這便實現了動態代理,是基於反射來實現代理。
其優點在於不重複的去創建代理類。
2、CGLIB動態代理
CGLIB動態代理是通過字節碼技術來實現的,底層是通過使用ASM字節碼框架在JAVA ,JVM中實現虛擬代理類,通過攔截所代理類調用的方法,經行橫向切入(AOP)來進行實現的
@兩種動態代理的區別在於
1、JDK是需要一個接口來進行代理的,這樣才能進行代理,個人感覺(原因是在於類於類之間存在關聯才能進行多態創建)
2、CGLIB動態代理,是不要接口就能進行代理,因爲底層使用的是字節碼技術,也就是說直接重寫你的代碼,而不需要實現。
在這裏需要提醒一下,CGLIB的性能,效率會比JDK的動態代理快上一點
但是經過專人測試,結果在使用JDK1.7或1.8與CGLIB,在相同環境下進行1w次測試,JDK效率比CGLIB快上20%,2333
注:此篇文章爲博主第一次寫,如果覺得有問題,或者說的有錯誤,可以加博主個人QQ412958751,十分感謝提出意見,一起學習