熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

Java中的靜態代理和動態代理

2013-11-23 18:49:20  來源: Java核心技術 

   代理模式主要有兩種靜態代理和動態代理

   靜態代理

  比如要在輸出HelloWorld前打印一個字符串Welcome

  A:先定義一個接口類

  Java代碼

  package ttitflyproxy;

  public interface HelloWorld {

  public void print();

  //  public void say();

  }

  package ttitflyproxy;

  public interface HelloWorld {

  public void print();

  //  public void say();

  }

  B: 定義一個該接口的實現類

  Java代碼

  package ttitflyproxy;

  public class HelloWorldImpl implements HelloWorld{

  public void print(){

  Systemoutprintln(HelloWorld);

  }

  //  public void say(){

  //      Systemoutprintln(Say Hello!);

  //  }

  }

  package ttitflyproxy;

  public class HelloWorldImpl implements HelloWorld{

  public void print(){

  Systemoutprintln(HelloWorld);

  }

  //  public void say(){

  //      Systemoutprintln(Say Hello!);

  //  }

  }

  C:定義一個靜態代理類

  Java代碼

  package ttitflyproxy;

  public class StaticProxy implements HelloWorld{

  public HelloWorld helloWorld ;

  public StaticProxy(HelloWorld helloWorld){

  thishelloWorld = helloWorld;

  }

  public void print(){

  Systemoutprintln(Welcome);

  //相當於回調

  helloWorldprint();

  }

  //  public void say(){

  //      //相當於回調

  //      helloWorldsay();

  //  }

  }

  package ttitflyproxy;

  public class StaticProxy implements HelloWorld{

  public HelloWorld helloWorld ;

  public StaticProxy(HelloWorld helloWorld){

  thishelloWorld = helloWorld;

  }

  public void print(){

  Systemoutprintln(Welcome);

  //相當於回調

  helloWorldprint();

  }

  //  public void say(){

  //      //相當於回調

  //      helloWorldsay();

  //  }

  }

  D: 一個測試類:

  Java代碼

  package ttitflyproxy;

  public class TestStaticProxy {

  public static void main(String[] args){

  HelloWorld helloWorld = new HelloWorldImpl();

  StaticProxy staticProxy = new StaticProxy(helloWorld);

  staticProxyprint();

  //      staticProxysay();

  }

  }

  package ttitflyproxy;

  public class TestStaticProxy {

  public static void main(String[] args){

  HelloWorld helloWorld = new HelloWorldImpl();

  StaticProxy staticProxy = new StaticProxy(helloWorld);

  staticProxyprint();

  //      staticProxysay();

  }

  }

  可以看出靜態代理類有一個很不爽的缺點當如果接口加一個方法(把上面所有的代碼的注釋給去掉)所有的實現類和代理類裡都需要做個實現這就增加了代碼的復雜度動態代理就可以避免這個缺點

   動態代理

  動態代理與普通的代理相比較最大的好處是接口中聲明的所有方法都被轉移到一個集中的方法中處理(invoke)這樣在接口方法數量比較多的時候我們可以進行靈活處理而不需要像靜態代理那樣每一個方法進行中轉

  動態代理類只能代理接口代理類都需要實現InvocationHandler類實現invoke方法該invoke方法就是調用被代理接口的所有方法時需要調用的該invoke方法返回的值是被代理接口的一個實現類

  代理類

  Java代碼

  package ttitflyproxy;

  import javalangreflectInvocationHandler;

  import javalangreflectMethod;

  import javalangreflectProxy;

  //動態代理類只能代理接口代理類都需要實現InvocationHandler類實現invoke方法該invoke方法就是調用被代理接口的所有方法時需要調用的該invoke方法返回的值是被代理接口的一個實現類

  public class DynamicProxy implements InvocationHandler{

  private Object object;

  //綁定關系也就是關聯到哪個接口(與具體的實現類綁定)的哪些方法將被調用時執行invoke方法

  //ProxynewProxyInstance的第三個參數是表明這些被攔截的方法執行時需要執行哪個InvocationHandler的invoke方法

  public Object bindRelation(Object object){

  thisobject = object;

  return ProxynewProxyInstance(objectgetClass()getClassLoader() objectgetClass()getInterfaces()this);

  }

  //攔截關聯的這個實現類的方法被調用時將被執行

  public Object invoke(Object proxy Method method Object[] args) throws Throwable {

  Systemoutprintln(Welcome);

  Object result = methodinvoke(object args);

  return result;

  }

  }

  package ttitflyproxy;

  import javalangreflectInvocationHandler;

  import javalangreflectMethod;

  import javalangreflectProxy;

  //動態代理類只能代理接口代理類都需要實現InvocationHandler接口覆蓋invoke方法該invoke方法就是調用被代理接口的所有方法時需要調用的該invoke方法返回的值是被代理接口的一個實現類

  public class DynamicProxy implements InvocationHandler{

  private Object object;

  //綁定關系也就是關聯到哪個接口(與具體的實現類綁定)的哪些方法將被調用時執行invoke方法

  //ProxynewProxyInstance的第三個參數是表明這些被攔截的方法執行時需要執行哪個InvocationHandler的invoke方法

  public Object bindRelation(Object object){

  thisobject = object;

  return ProxynewProxyInstance(objectgetClass()getClassLoader() objectgetClass()getInterfaces()this);

  }

  //攔截關聯的這個實現類的方法被調用時將被執行

  public Object invoke(Object proxy Method method Object[] args) throws Throwable {

  Systemoutprintln(Welcome);

  Object result = methodinvoke(object args);

  return result;

  }

  }

  測試類

  Java代碼

  package ttitflyproxy;

  public class TestDynamicProxy {

  public static void main(String[] args){

  HelloWorld helloWorld = new HelloWorldImpl();

  DynamicProxy dp = new DynamicProxy();

  //在這裡綁定的是HelloWorld也就是HelloWorld是被代理接口所以綁定關系時需要傳遞一個HelloWorld的實現類的實例化對象

  HelloWorld helloWorld = (HelloWorld)dpbindRelation(helloWorld);

  helloWorldprint();

  helloWorldsay();

  //helloWorld將不被攔截

  HelloWorld helloWorld = new HelloWorldImpl();

  helloWorldprint();

  helloWorldsay();

  }

  }

  package ttitflyproxy;

  public class TestDynamicProxy {

  public static void main(String[] args){

  HelloWorld helloWorld = new HelloWorldImpl();

  DynamicProxy dp = new DynamicProxy();

  //在這裡綁定的是HelloWorld也就是HelloWorld是被代理接口所以綁定關系時需要傳遞一個HelloWorld的實現類的實例化對象

  HelloWorld helloWorld = (HelloWorld)dpbindRelation(helloWorld);

  helloWorldprint();

  helloWorldsay();

  //helloWorld將不被攔截

  HelloWorld helloWorld = new HelloWorldImpl();

  helloWorldprint();

  helloWorldsay();

  }

  }

  在測試類裡調用實現類的print和say方法因為代理類裡代理了HelloWorld的所有方法所以就不需要像靜態代理類那樣一一實現了

  總結由程序員創建或由特定工具自動生成源代碼再對其編譯在程序運行前代理類的class文件就已經存在了

  動態代理類在程序運行時運用反射機制動態創建而成

  代理類可以為委托類預處理消息把消息轉發給委托類和事後處理消息等動態代理類的字節碼在程序運行時由Java反射機制動態生成無需程序員手工編寫它的源代碼動態代理類不僅簡化了編程工作而且提高了軟件系統的可擴展性因為Java 反射機制可以生成任意類型的動態代理類


From:http://tw.wingwit.com/Article/program/Java/hx/201311/25797.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.