當前位置:編程學習大全網 - 源碼下載 - 什麽是反射技術?什麽是靜態代理?什麽是動態代理?什麽是aop

什麽是反射技術?什麽是靜態代理?什麽是動態代理?什麽是aop

JAVA的靜態代理與動態代理比較 壹、概念 代理模式是常用的Java 設計模式,它的特征是代理類與委托類有同樣的接口,代理類主要負責為委托類預處理消息、過濾消息、把消息轉發給委托類,以及事後處理消息等。代理類與委托類之間通常會存在關聯關系,壹個代理類的對象與壹個委托類的對象關聯,代理類的對象本身並不真正實現服務,而是通過調用委托類的對象的相關方法,來提供特定的服務。按照代理類的創建時期,代理類可分為兩種。靜態代理類: 由程序員創建或由特定工具自動生成源代碼,再對其編譯。在程序運行前,代理類的.class文件就已經存在了。動態代理類:在程序運行時,運用反射機制動態創建而成。二、靜態代理類 如下, HelloServiceProxy 類是代理類,HelloServiceImpl類是委托類,這兩個類都實現了HelloService接口。其中HelloServiceImpl類是HelloService接口的真正實現者,而HelloServiceProxy類是通過調用HelloServiceImpl 類的相關方法來提供特定服務的。HelloServiceProxy類的echo()方法和getTime()方法會分別調用被代理的HelloServiceImpl 對象的echo()方法和getTime()方法,並且在方法調用前後都會執行壹些簡單的打印操作。由此可見,代理類可以為委托類預處理消息、把消息轉發給委托類和事後處理消息等。例程1 HelloService.javapackage proxy;import java.util.Date;public interface HelloService{ public String echo(String msg); public Date getTime();}例程2 HelloServiceImpl.javapackage 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.javapackage 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.javapackage 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.javapackage 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.javapackage 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,打印結果如下:動態代理類的名字為$Proxy0before 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程序生成日期類型的隨機函數?
  • 下一篇:使用VB語言編寫,在界面上畫個框,裏面顯示攝像頭裏的圖像
  • copyright 2024編程學習大全網