A. 怎麼理解java代理
mport 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方法。
B. Java代理的作用和實現
JDK 動態代理
動態代理的核心其實就是代理對象的生成,即 Proxy.newProxyInstance(classLoader, proxyInterface, handler)。
讓我們進入newProxyInstance方法觀摩下,核心代碼其實就三行。
這個方法需要三個參數:
ClassLoader,用於載入代理類的 Loader 類,通常這個 Loader 和被代理的類是同一個 Loader 類。
Interfaces,是要被代理的那些那些介面。
InvocationHandler,就是用於執行除了被代理介面中方法之外的用戶自定義的操作,也是用戶需要代理的最終目的。用戶調用目標方法都被代理到 InvocationHandler 類中定義的唯一方法 invoke 中。
一個典型的動態代理創建對象過程可分為以下四個步驟:
1、通過實現InvocationHandler介面創建調用處理器
2、通過為Proxy類指定ClassLoader對象和一組interface創建動態代理類
3、通過反射機制獲取動態代理類的構造函數,其參數類型是調用處理器介面類型
4、通過構造函數創建代理類實例,此時需將調用處理器對象作為參數被傳入
為了簡化對象創建過程,Proxy類中的newProxyInstance方法封裝了2~4,只需兩步即可完成代理對象的創建。
生成的proxySubject繼承Proxy類實現Subject介面。實現的Subject的方法實際是調用處理器的invoke方法,而invoke方法利用反射調用的是被代理對象的方法(Object result=method.invoke(proxied,args));
重點Proxy.newProxyInstance,源碼分析,會在其他文檔中單獨總結記錄。類Proxy的getProxyClass方法調用ProxyGenerator的 generateProxyClass方法產生ProxySubject.class的二進制數據。
創建代理對象時序圖
獲取代理類
getProxyClass(loader, interfaces)方法用於獲取代理類,它主要做了三件事情:
在當前類載入器的緩存里搜索是否有代理類,沒有則生成代理類並緩存在本地JVM里。
生成並載入代理類
代理類的生成主要是以下這兩行代碼:
代理類的生成過程
ProxyGenerator.generateProxyClass()方法屬於sun.misc包下,Oracle並沒有提供源代碼,但是我們可以使用
JD-GUI這樣的反編譯軟體打開jrelib
t.jar來一探究竟,以下是其核心代碼的分析。
生成的代理類源碼
那麼通過以上分析,我們可以推出動態代理為我們生成了一個這樣的代理類。把方法doSomeThing的方法體修改為調用LogInvocationHandler的invoke方法。
測試代理的代碼如下:
下面看一個自定義代理的實現。
被代理類介面
被代理類
調用處理器(切面)
測試我們的代理實現
運行結果:
Proxy 介面
Proxy 的主要靜態變數
ProxySubject 源碼
創建的代理類 ProxySubject.class
CGLib 動態代理
動態位元組碼生成。使用動態位元組碼生成技術實現AOP原理是在運行期間目標位元組碼載入後,生成目標類的子類,將切面邏輯加入到子類中,所以使用Cglib實現AOP不需要基於介面。
C. Java中動態代理是什麼意思
舉個例子吧,比如說你暗戀一個小美女,你給她寫了個情書,你不好意思直接給她,就讓我轉給她。
我也暗戀這個小美女,我收到你的情書以後,我送你的情書之前跟小美女說你這個人人品差長得丑還沒錢,然後再把你的情書給她。
動態代理就是這個過程。本來是你和小美女之間的關系,但中間讓我轉達一下,我在轉達的前後可以干一些自己的事情。更具體的說,就是A調用B,但不直接調用,A通過調用C,C再調用B,C在調用B的前後可以做一些自己的事情,比如說打日誌、許可權驗證等,這樣就把業務代碼與系統代碼分開,同時減少了A和B之間的耦合。
動態代理的經典應用是Spring AOP。有興趣可以學學。
D. 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。
PostScript
E. Java代理的三種模式有什麼
Java的三種代理模式簡述
本文著重講述三種代理模式在java代碼中如何寫出,為保證文章的針對性,暫且不討論底層實現原理,具體的原理將在下一篇文章中講述。
代理模式是什麼
代理模式是一種設計模式,簡單說即是在不改變源碼的情況下,實現對目標對象的功能擴展。
比如有個歌手對象叫Singer,這個對象有一個唱歌方法叫sing()。
假如你希望,通過你的某種方式生產出來的歌手對象,在唱歌前後還要想觀眾問好和答謝,也即對目標對象Singer的sing方法進行功能擴展。
但是往往你又不能直接對源代碼進行修改,可能是你希望原來的對象還保持原來的樣子,又或許你提供的只是一個可插拔的插件,甚至你有可能都不知道你要對哪個目標對象進行擴展。這時就需要用到java的代理模式了。網上好多用生活中的經理人的例子來解釋「代理」,看似通俗易懂,但我覺得不適合程序員去理解。程序員應該從代碼的本質入手。
F. 什麼是JAVA代理模式,一直理解不了。
簡單點說就是你要調用一個介面test(),這裡面有一個」說話「的方法,當你實例化之後就可以調用這方法,但是你發現你不止要」說話「這個功能,你還要實現一個」吃飯「sing()的功能,
那麼我們既不能在test介面里增加sing()方法,又不能在每個前端都增加sing方法,我們只有增加一個代理類talkProxy,這個代理類里實現talk和sing方法,然後在需要sing方法的客戶端調用代理類即可.大概就是這個意思 全手打, 望採納。
G. java中的代理有什麼用
主要就是包裝被代理類,注冊一個回調類,攔截被代理類調用,執行相關操作,spring的aop就可以用代理來實現
H. 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方法。
I. 什麼是代理模式(java中的)
為其他對象提供一種代理以控制對這個對象的訪問.
代理是比較有用途的一種模式,而且變種較多,應用場合覆蓋從小結構到整個系統的大結構,我們也許有代理伺服器等概念,代理概念可以解釋為:在出發點到目的地之間有一道中間層,意為代理.
詳細可參考java設計模式手冊
J. java中的代理,反射指是什麼意思
樓主您好
代理就是 本來你要用這個類的方法,但這個類的方法還不夠滿足你的需求,你可以為他創建一個代理類,一般有java的代理和cglib,一種通過實現同一介面 一種是創建一個繼承主類的子類。比如有人要租房,你是房東,代理類就是中介。
反射意思就是 實現類似這樣的功能,比如我傳入某個(比如x)字元串,我就要調用setX這個方法。這種就需要用反射來實現。當然 反射遠不止這些,很多框架的技術都是用反射實現的。比如通過你的配置文件來調用不同的方法。