導航:首頁 > 代理服務 > java為什麼要有動態代理

java為什麼要有動態代理

發布時間:2023-06-15 02:13:23

1. java動態代理是什麼

import java.lang.reflect.Proxy;
A. 創建一個實現介面InvocationHandler的類,他必須實現invoke方法
B. 創建被代理的類以及介面。
C. 通過Proxy的靜態方法newProxyInstance(ClassLoader loader,Class【】interfaces,InvocationHandler handler)創建一個代理
D. 通過代理調用方法。
java動態代理:是在運行是生成的class對象,在生成時必須提供一組或一個interface給它,然後該class就宣稱它實現了這些interface。你當然可以把該class的實例當做這些interface中的任何一個來用,當然,這個DynamicProxy其實就是一個Proxy,他不會替你做實質性的工作,在生成它的實例時你必須提供一個handler,由它接管實際的工作。因此,DynamicProxy必須實現InvocationHandler介面。
5) 一個動態代理了和一個InvocationHandler 實現關聯的。每一個動態代理實例的調用都要通過InvocationHandler介面的handler(調用處理器)來調用,動態代理不做任何執行操作,只是在創建動態代理時,把要實現的介面和handler關聯,動態代理要幫助被代理執行的任務,要轉交給handler來執行。其實就是調用invoke方法。

2. java 動態代理是基於什麼原理

反射機制是java語言提供的一種基礎功能,賦予程序在運行時自省的能力。通過反射我們可以直接操作類或者對象,比如獲取某個對象的類定義,獲取類聲明的屬性和方法,調用方法或者構造對象,甚至可以運行時修改類定義。
動態代理是一種方便運行時動態構建代理、動態處理代理方法調用的機制,很多場景都是利用類似機製做到的,比如用來包裝RPC調用、面向切面的編程。
實現動態代理的方式很多,比如JDK自身提供的動態代理,就是主要利用了上面提到的反射機制。還有其他的實現方式,比如利用傳說中更高性能的位元組碼操作機制,類似ASM、aglib、Javassist等。

3. Java代理的作用和實現

JDK 動態代理

動態代理的核心其實就是代理對象的生成,即 Proxy.newProxyInstance(classLoader, proxyInterface, handler)。

讓我們進入newProxyInstance方法觀摩下,核心代碼其實就三行。

這個方法需要三個參數:

4. java中動態代理是怎麼回事,和靜態代理最大的區別是什麼

JAVA的靜態代理與動態代理比較
一、概念
代理模式是常用的Java 設計模式,它的特徵是代理類與委託類有同樣的介面,代理類主要負責為委託類預處理消息、過濾消息、把消息轉發給委託類,以及事後處理消息等。代理類與委託類之間通常會存在關聯關系,一個代理類的對象與一個委託類的對象關聯,代理類的對象本身並不真正實現服務,而是通過調用委託類的對象的相關方法,來提供特定的服務。按照代理類的創建時期,代理類可分為兩種。

靜態代理類:
程序員創建或由特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了。動態代理類:在程序運行時,運用反射機制動態創建而成。

二、靜態代理類
如下, HelloServiceProxy 類是代理類,HelloServiceImpl類是委託類,這兩個類都實現了HelloService介面。其中HelloServiceImpl類是HelloService介面的真正實現者,而HelloServiceProxy類是通過調用HelloServiceImpl 類的相關方法來提供特定服務的。HelloServiceProxy類的echo()方法和getTime()方法會分別調用被代理的HelloServiceImpl 對象的echo()方法和getTime()方法,並且在方法調用前後都會執行一些簡單的列印操作。

由此可見,代理類可以為委託類預處理消息、把消息轉發給委託類和事後處理消息等。

常式1 HelloService.java
package proxy;
import java.util.Date;
public interface HelloService{
public String echo(String msg);
public Date getTime();
}
常式2 HelloServiceImpl.java
package proxy;
import java.util.Date;
public class HelloServiceImpl implements HelloService{
public String echo(String msg){
return "echo:"+msg;
}
public Date getTime(){
return new Date();
}
}
常式3 HelloServiceProxy.java
package proxy;
import java.util.Date;
public class HelloServiceProxy implements HelloService{
private HelloService helloService; //表示被代理的HelloService 實例
public HelloServiceProxy(HelloService helloService){
this.helloService=helloService;
}
public void setHelloServiceProxy(HelloService helloService){
this.helloService=helloService;
}
public String echo(String msg){
System.out.println("before calling echo()"); //預處理
String result=helloService.echo(msg); //調用被代理的HelloService 實例的echo()方法
System.out.println("after calling echo()"); //事後處理
return result;
}
public Date getTime(){
System.out.println("before calling getTime()"); //預處理
Date date=helloService.getTime(); //調用被代理的HelloService 實例的getTime()方法
System.out.println("after calling getTime()"); //事後處理
return date;
}
}
在Client1 類的main()方法中,先創建了一個HelloServiceImpl對象,又創建了一個HelloServiceProxy對象,最後調用HelloServiceProxy對象的echo()方法。
常式4 Client1.java
package proxy;
public class Client1{
public static void main(String args[]){
HelloService helloService=new HelloServiceImpl();
HelloService helloServiceProxy=new HelloServiceProxy(helloService);
System.out.println(helloServiceProxy.echo("hello"));
}
}
運行Client1 類,列印結果如下:
before calling echo()
after calling echo()
echo:hello
常式3 的HelloServiceProxy 類的源代碼是由程序員編寫的,在程序運行前,它的.class文件就已經存在了,這種代理類稱為靜態代理類。

三、動態代理類
與靜態代理類對照的是動態代理類,動態代理類的位元組碼在程序運行時由Java反射機制動態生成,無需程序員手工編寫它的源代碼。動態代理類不僅簡化了編程工作,而且提高了軟體系統的可擴展性,因為Java 反射機制可以生成任意類型的動態代理類。java.lang.reflect 包中的Proxy類和InvocationHandler 介面提供了生成動態代理類的能力。

Proxy類提供了創建動態代理類及其實例的靜態方法。
(1)getProxyClass()靜態方法負責創建動態代理類,它的完整定義如下:

public static Class<?> getProxyClass(ClassLoader loader, Class<?>[] interfaces) throws IllegalArgumentException

參數loader 指定動態代理類的類載入器,參數interfaces 指定動態代理類需要實現的所有介面。

(2)newProxyInstance()靜態方法負責創建動態代理類的實例,它的完整定義如下:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler) throws
IllegalArgumentException

參數loader 指定動態代理類的類載入器,參數interfaces 指定動態代理類需要實現的所有介面,參數handler 指定與動態代理類關聯的 InvocationHandler 對象。

以下兩種方式都創建了實現Foo介面的動態代理類的實例:
/**** 方式一 ****/
//創建InvocationHandler對象
InvocationHandler handler = new MyInvocationHandler(...);

//創建動態代理類
Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class });

//創建動態代理類的實例
Foo foo = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });

/**** 方式二 ****/
//創建InvocationHandler對象
InvocationHandler handler = new MyInvocationHandler(...);

//直接創建動態代理類的實例
Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[] { Foo.class }, handler);

由Proxy類的靜態方法創建的動態代理類具有以下特點:
動態代理類是public、final和非抽象類型的;
動態代理類繼承了java.lang.reflect.Proxy類;
動態代理類的名字以「$Proxy」開頭;
動態代理類實現getProxyClass()和newProxyInstance()方法中參數interfaces指定的所有介面;

Proxy 類的isProxyClass(Class<?> cl)靜態方法可用來判斷參數指定的類是否為動態代理類。只有通過Proxy類創建的類才是動態代理類;

動態代理類都具有一個public 類型的構造方法,該構造方法有一個InvocationHandler 類型的參數。

由Proxy類的靜態方法創建的動態代理類的實例具有以下特點:
1. 假定變數foo 是一個動態代理類的實例,並且這個動態代理類實現了Foo 介面,那麼「foo instanceof Foo」的值為true。把變數foo強制轉換為Foo類型是合法的:
(Foo) foo //合法

2.每個動態代理類實例都和一個InvocationHandler 實例關聯。Proxy 類的getInvocationHandler(Object proxy)靜態方法返回與參數proxy指定的代理類實例所關聯的InvocationHandler 對象。

3.假定Foo介面有一個amethod()方法,那麼當程序調用動態代理類實例foo的amethod()方法時,該方法會調用與它關聯的InvocationHandler 對象的invoke()方法。

InvocationHandler 介面為方法調用介面,它聲明了負責調用任意一個方法的invoke()方法:
Object invoke(Object proxy,Method method,Object[] args) throws Throwable

參數proxy指定動態代理類實例,參數method指定被調用的方法,參數args 指定向被調用方法傳遞的參數,invoke()方法的返回值表示被調用方法的返回值。

四、最後看一個實例:
HelloServiceProxyFactory 類的getHelloServiceProxy()靜態方法負責創建實現了HelloService介面的動態代理類的實例。

常式5 HelloServiceProxyFactory.java
package proxy;
import java.lang.reflect.*;
public class HelloServiceProxyFactory {
/** 創建一個實現了HelloService 介面的動態代理類的實例
* 參數helloService 引用被代理的HelloService 實例
*/
public static HelloService getHelloServiceProxy(final HelloService helloService){
//創建一個實現了InvocationHandler介面的匿名類的實例
InvocationHandler handler=new InvocationHandler(){
public Object invoke(Object proxy,Method method,Object args[])throws Exception{
System.out.println("before calling "+method); //預處理
Object result=method.invoke(helloService,args);
//調用被代理的HelloService 實例的方法
System.out.println("after calling "+method); //事後處理
return result;
}
};
Class classType=HelloService.class;
return (HelloService)Proxy.newProxyInstance(classType.getClassLoader(),
new Class[]{classType},
handler);
}
}
如下所示的Client2 類先創建了一個HelloServiceImpl 實例,然後創建了一個動態代理類實例helloServiceProxy,最後調用動態代理類實例的echo()方法。
常式6 Client2.java
package proxy;
public class Client2{
public static void main(String args[]){
HelloService helloService=new HelloServiceImpl();
HelloService helloServiceProxy=HelloServiceProxyFactory.getHelloServiceProxy(helloService);
System.out.println("動態代理類的名字為"+helloServiceProxy.getClass().getName());
System.out.println(helloServiceProxy.echo("Hello"));
}
}
運行Client2,列印結果如下:
動態代理類的名字為$Proxy0
before calling public abstract java.lang.String proxy.HelloService.echo(java.lang.String)
after calling public abstract java.lang.String proxy.HelloService.echo(java.lang.String)
echo:Hello
從結果看出,動態代理類的名字為$Proxy0。

5. Java中的動態代理相對於靜態代理有何優點

缺Java中的動態代理相對於靜態代理優點:
1、靜態代理類和委託類實現了相同的介面,代理類通過委託類實現了相同的方法。這樣就出現了大量的代碼重復。如果介面增加一個方法,除了所有實現類需要實現這個方法外,所有代理類也需要實現此方法。增加了代碼維護的復雜度。
2、靜態代理對象只服務於一種類型的對象,如果要服務多類型的對象。勢必要為每一種對象都進行代理,靜態代理在程序規模稍大時就無法勝任了。如上的代碼是只為UserManager類的訪問提供了代理,但是如果還要為其他類如Department類提供代理的話,就需要我們再次添加代理Department的代理類。

6. JAVA動態代理設計原理及如何實現

Java動態代理機制的出現,使得Java開發人員不用手工編寫代理類,只要簡單地制定一組介面及委託類對象,便能動態地獲得代理類。代理類會負責將所有的方法調用分配到委託對象上反射執行,配置執行過程中,開發人員還可以進行修改

代理設計模式

代理是一種常用的設計模式,其目的就是為其他對象提供一個代理以控制對某個對象的訪問。代理類負責為委託類預處理消息、過濾消息並轉發消息,以及進行消息被委託類執行後的後續處理。

  1. 為了保持行為的一致性,代理類和委託類通常會實現相同的介面

2. 引入代理能夠控制對委託對象的直接訪問,可以很好的隱藏和保護委託對象,也更加具有靈活性

代理機制及其特點

首先讓我們來了解一下如何使用 Java 動態代理。具體有如下四步驟:

  1. 通過實現 InvocationHandler 介面創建自己的調用處理器;

  2. 通過為 Proxy 類指定 ClassLoader 對象和一組 interface 來創建動態代理類;

  3. 通過反射機制獲得動態代理類的構造函數,其唯一參數類型是調用處理器介面類型;

  4. 通過構造函數創建動態代理類實例,構造時調用處理器對象作為參數被傳入。

代理類實例的一些特點

  1. 每個實例都會關聯一個InvocationHandler(調用處理器對象),在代理類實例上調用其代理介面中聲明的方法時,最終都會由InvocationHandler的invoke方法執行;

  2. java.lang.Object中有三個方法也同樣會被分派到調用處理器的 invoke 方法執行,它們是 hashCode,equals 和 toString;

代碼示例

最後以一個簡單的動態代理例子結束

7. java 我不理解動態代理的意義

人家是動態編程,需要在原來的方法的功能基礎上再添加一些功能,而不用改變這個方法的簽名,原來調用這個方法的類依然能正常工作。

比如,現在要把一段文本發送給另一個人,普通方法是 void send(File a),現在我們弄出個特性,就像 Spring AOP 那樣,在 send 之前給這個 a 壓縮一下。原來的程序沒有壓縮功能,現在我們需要添加的話而不改變原來所有的代碼的話就得用類似 AOP 這樣的代碼來處理。

一般一個無法再繼承的類和方法,要用代理,而能夠繼承的類和方法可以在內在中直接生成一個新的 java 類繼承它然後覆蓋掉那個 send 方法,像 hibernate/spring/jboss 都把這些自動完成了。
而像 AspectJ 這種 AOP 剛不同,它直接把人家的 class 代碼修改了,它就不需要使用代理。

這些在新的 JDK 6 中都可以通過 Instrument 來做到,不過也是個通用的方法,還得通過規則來定製什麼情況下處理,什麼時候不處理。

閱讀全文

與java為什麼要有動態代理相關的資料

熱點內容
微博一周數據怎麼看 瀏覽:104
床上用品批發市場哪裡 瀏覽:810
影響產品銷售成本的因素有哪些 瀏覽:34
曼龍怎麼做代理 瀏覽:539
大學駕校如何找代理 瀏覽:61
怎麼銷售開拓檳榔市場 瀏覽:870
信息輔助家園共育活動有什麼 瀏覽:446
廣州服裝批發市場白馬什麼定位 瀏覽:622
產品定製需要什麼標志 瀏覽:76
信息隱藏在現實生活中應用於哪些方面 瀏覽:804
參與網路信息犯罪要多久才判 瀏覽:464
要想扎針技術好應該怎麼做 瀏覽:597
二手房買賣交易流程是什麼 瀏覽:939
充紅包銀行拒絕交易怎麼回事 瀏覽:195
抖音數據清空了怎麼恢復 瀏覽:470
技術學院指哪些 瀏覽:516
開店做什麼生意好加盟代理 瀏覽:31
增益開關技術是什麼 瀏覽:500
隱藏的程序什麼也看不見 瀏覽:819
工程技術專業能考什麼證書 瀏覽:360