導航:首頁 > 編程語言 > java反射與動態代理

java反射與動態代理

發布時間:2023-07-10 10:55:54

㈠ 什麼是反射技術什麼是靜態代理什麼是動態代理什麼是aop

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。

㈡ java中的反射機制是什麼,有什麼作用啊

Method類中的方法的使用(含代碼和注釋):

getMethods()獲得本類及父類中的public許可權修飾**符方法
getDeclaredMethods()專門獲得調用該方法的對象的本類中的所有方法包括private許可權修飾符**的方法
getDeclaredMethod(Stringname,class<?>...parameterTypes)
第一個參數:方法的名稱
第二個參數:可變長度,寫你要查找的那個方法的參數類型列表.class
getParameterCount()得到方法的參數個數123456
packageLessonForReflection03;importjava.lang.reflect.Method;importjava.lang.reflect.Modifier;abstractclassCard{
privatevoidcreatRandomNumbers(intcount)//private關鍵字
{

}

publicvoidgetFullCardsNumbers(String[]random,Stringpre_numbers)
{

}

publicstaticvoidgetUserInfor()
{

}

(Stringtel);

(intsal1,intsal2),ArithmeticException;}publicclassMethodInforGetter{

publicstaticvoidmain(String[]args)
{
Class<?>c1=Card.class;

System.out.println("-------------------------");

Method[]m1=c1.getMethods();//getMethods()獲得本類及父類中的public方法!
for(Methodm:m1)
{
System.out.println(m);
}

System.out.println("-------------------------");

Method[]m2=c1.getDeclaredMethods();//getDeclaredMethods()專門獲得本類中的所有方法包括private!
for(Methodm:m2)
{
System.out.println(m);
}

System.out.println("-------------------------");

/*
*getDeclaredMethod(Stringname,class<?>...parameterTypes)
*第一個參數:方法的名稱
*第二個參數:可變長度,寫你要查找的那個方法的參數類型列表
*
*getParameterCount()得到方法的參數個數
*/

try
{
Methodm3=c1.getDeclaredMethod("getUserInfor");
System.out.println(m3);

//getParameterCount()方法,獲得方法參數個數
System.out.println(m3.getParameterCount());
System.out.println(Modifier.toString(m3.getModifiers()));//獲得方法修飾符
System.out.println(m3.getReturnType());

System.out.println("-------------------------");

Methodm4=c1.getDeclaredMethod("getUserInfor",int.class,int.class);

//getExceptionTypes()可以獲得初始化當前Method對象的給Class對象初始化的那個類的那個指定方法拋出的異常類型
Class<?>[]exception=m4.getExceptionTypes();
for(Class<?>e:exception)
{
System.out.println(e);
}

}catch(NoSuchMethodException|SecurityExceptione)
{
e.printStackTrace();
}
}}576777879808182838485868788

Constructor類中的方法的使用www.xiaoyuani.com(含代碼和注釋):

java.lang.reflect.Constructor:
Constructor[]getConstructor()獲得本類里的public許可權修飾符構造函數,不能獲取父類的!
Constructor[]getDeclaredConstructor()獲得本類中的所以構造函數!
Constructor<T>getConstructor(Class...parameterType)用參數決定獲得本類中的某個的構造方法,只能獲得public的
Constructor<T>getDeclaredConstructor(Class...parameterType)用參數決定獲得本類中的某個構造方法
附:
JDK8.0之後新增的類:
Executable:
它是Method和Constructor的父類
常用方法:
getParameter()獲得類中方法參數
getExceptionTypes()獲得類中某個方法拋出異常類型
getMoidfiers()獲得方法許可權修飾符
Parameter:
封裝並代表了參數實例123456789101112131415
packageLessonForReflection03;importjava.lang.reflect.Constructor;importjava.lang.reflect.Modifier;importjava.lang.reflect.Parameter;/*
*java.lang.reflect.Constructor
*
*Constructor[]getConstructor();獲得本類里的public許可權修飾符構造函數,不能獲取父類的
*Constructor[]getDeclaredConstructor();得本類里的全部構造
*
*Constructor<T>getConstructor(Class...parameterType);用參數決定獲得哪個構造方法
*Constructor<T>getDeclaredConstructor(Class...parameterType);
*
*/{
publicstaticvoidmain(String[]args)
{
System.out.println("獲得Cricle本類里的public許可權修飾符構造函數,不能獲取父類的Constructor[]getConstructor()");
System.out.println("子類繼承不了父類中的構造方法和private");
//Constructor[]getConstructor()獲得Cricle本類里的public許可權修飾符構造函數,不能獲取父類的
//子類繼承不了父類中的構造方法和private
Class<Circle>c1=Circle.class;
Constructor<?>[]cons1=c1.getConstructors();
for(Constructor<?>cons:cons1)
{
System.out.println(cons);
//System.out.println(cons.getName());
}

System.out.println("-----------------------");

System.out.println("方法獲得本類中的所有構造函數getDeclaredConstructor()");
Constructor<?>[]cons2=c1.getDeclaredConstructors();
for(Constructor<?>cons:cons2)
{
System.out.println(cons);
}

System.out.println("-----------------------");

try
{
System.out.println("方法用參數指定獲得本類!構造方法,只能獲取public的Constructor<T>getConstructor(Class...parameterType)");
Constructor<?>cons3=c1.getConstructor(int.class);
System.out.println(Modifier.toString(cons3.getModifiers()));
System.out.println(cons3);

System.out.println("-----------------------");

System.out.println("方法用參數指定獲得本類!構造方法任何許可權修飾符的都可以獲得Constructor<T>getDeclaredConstructor(Class...parameterType)");
Constructor<?>cons4=c1.getDeclaredConstructor(String.class);
System.out.println(cons4);

System.out.println("-----------------------");

/*
*JDK8.0之後新增的類
*Executable:
*是Method和Constructor的父類
*方法:
*getParameter();
*getExceptionTypes();
*getModifiers();
*getTypeParameters();
*
*Parameter:
*封裝並代表了參數實例
*/
System.out.println("獲取類中方法的參數getParameters()");
Constructor<?>cons5=c1.getDeclaredConstructor(int.class,String.class);
Parameter[]p1=cons5.getParameters();
for(Parameterp:p1)
{
System.out.println(p);
}
}catch(NoSuchMethodException|SecurityExceptione)
{
e.printStackTrace();
}

}}5767778798081828384858687

代碼中提到的Circle類和Shape類二者為繼承關系:

packageLessonForReflection03;publicclassCircleextendsShape{
privateintr;
privateStringcolor;

publicCircle(intr,Stringcolor)
{
super();
this.r=r;
this.color=color;
}

publicCircle(intr)
{
super();
this.r=r;
}

protectedCircle(Stringcolor)
{
super();
this.color=color;
}

Circle()
{
super();
}}
packageLessonForReflection03;publicclassShape{
privateintper;

publicShape(intper)
{
super();
this.per=per;
}

publicShape()
{
super();
}}1234567891011121314151617

部分文字來源於:
咕嘟咖啡楊海濱老師 — 《java編程語言高級特性》
輕量化研習Java相關技術倡導者
「愛碼學院」聯合創始人自適應教學理念提出者踐行者;多年開發及項目管理經歷;出版《JavaEE企業級應用與開發》一書;10餘年高校項目實踐畢設指導經驗;企業軟培經驗豐富

㈢ JAVA中反射是什麼

JAVA中反射是動態獲取信息以及動態調用對象方法的一種反射機制。

Java反射就是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意方法和屬性;並且能改變它的屬性。而這也是Java被視為動態語言的一個關鍵性質。

Java反射的功能是在運行時判斷任意一個對象所屬的類,在運行時構造任意一個類的對象,在運行時判斷任意一個類所具有的成員變數和方法,在運行時調用任意一個對象的方法,生成動態代理。

(3)java反射與動態代理擴展閱讀:

JAVA中反射實例:

1、Class superClass=clazz.getSuperclass();//獲取父類。

System.out.println("getSuperclass:"+superClass)。

2、Class[] interfaces=clazz.getInterfaces();//獲取實現介面。

System.out.println("getInterfaces:"+interfaces.length)。

3、Constructor[] cons=clazz.getConstructors();//構造方法。

System.out.println("getConstructors:"+cons.length)。

參考資料來源:網路: JAVA反射機制

㈣ Java的反射到底有什麼用途

反射的作用可謂是博大精深,

  1. JDK動態代理生成代理類的位元組碼後,首先把這個類通過defineclass定義成一個類,然後用class.for(name)會把該類載入到jvm,之後我們就可以通過,A.class.GetMethod()獲取其方法,然後通過invoke調用其方法,在調用這個方法時,實際上會通過被代理類的引用再去調用原方法。

  2. Java反射包reflection提供對Class,Method,field,constructor1 等信息的封裝類型

  3. 通過這些api可以輕易獲得一個類的各種信息並且可以進行實例化,方法調用等。
    類中的private參數可以通過setaccessible方法強制獲取。

㈤ java中什麼是反射,反射怎麼用,什麼場景用有沒有替代方案

1、反射簡言之就是在編譯時無法拿到某一個類,但是可以在運行時動態獲取這個類,這樣去使用某一個類,就是反射的使用場景。
2、代替反射或者類似的操作,可以通過DI實現IOC .依賴注入,動態代理。

閱讀全文

與java反射與動態代理相關的資料

熱點內容
伺服器網卡有什麼好處 瀏覽:90
javasql格式化 瀏覽:599
小愛同學機器人的命令詞 瀏覽:971
檢驗signature的php示例代碼 瀏覽:161
android內錄 瀏覽:776
騰訊雲輕量應用伺服器服務商 瀏覽:176
平板app打不開怎麼回事 瀏覽:317
九號怎麼用app控制前後移動 瀏覽:617
pdf瀏覽器預覽 瀏覽:695
六一兒童節程序員爸爸 瀏覽:166
農村電視天線加密 瀏覽:903
freepdfword 瀏覽:752
程序員怎麼做舔狗 瀏覽:584
怎麼保養汽車空調壓縮機 瀏覽:756
黑客與逆向工程師的python編程之道 瀏覽:864
企業信息化pdf 瀏覽:57
如何給男孩子解壓 瀏覽:735
伺服器雲轉發源ip 瀏覽:29
電腦伺服器地址指的什麼 瀏覽:955
蘋果怎麼下載匯成銀行app 瀏覽:899