代理模式的簡易講解

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、代理模式

代理模式分爲一下幾種

  1. 靜態代理模式

  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差不多了

靜態代理優點以及缺點

  1. 優點:

可擴展性強

代碼簡潔不影響源代碼的使用

     2.缺點

每一次代理都需要產生一個代理類

重複的代理類使得代碼效率過低

4、動態代理模式

1、JDK動態代理

2、CGLIB動態代理

5、這兩種動態代理模式有什麼區別呢?

  1. 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,十分感謝提出意見,一起學習

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章