Java动态代理

  在学习《Java编程思想》的时候看到了动态代理,觉得很有意思,现在来做一下总结。

一、代理模式的定义

  为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

二、优点

  (1).职责清晰真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
  (2).代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的作用。
  (3).高扩展性

三、模式结构

  一个是真正的你要访问的对象(目标类),一个是代理对象,真正对象与代理对象实现同一个接口,先访问代理类再访问真正要访问的对象。

四、UML示意图

 

Java动态代理

  我们来看一个普通代理实现的例子:

 1 //客户端接口

 2 interface Interface {  3 

 4     void doSomething();  5 

 6     void somethingElse(String arg);  7 }  8 

 9 //客户端实现类,就是执行业务逻辑的类

10 class RealObject implements Interface { 11 

12  @Override 13     public void doSomething() { 14         // TODO Auto-generated method stub

15         System.out.println("doSomething"); 16  } 17 

18  @Override 19     public void somethingElse(String arg) { 20         // TODO Auto-generated method stub

21         System.out.println("somethingElse" + arg); 22  } 23 

24 } 25 

26 //代理类

27 class SimpleProxy implements Interface { 28 

29     private Interface proxied; 30 

31     public SimpleProxy(Interface proxied) { 32         // TODO Auto-generated constructor stub

33         this.proxied = proxied; 34  } 35 

36  @Override 37     public void doSomething() { 38         // TODO Auto-generated method stub

39         System.out.println("SimpleProxy doSomething"); 40  proxied.doSomething(); 41  } 42 

43  @Override 44     public void somethingElse(String arg) { 45         // TODO Auto-generated method stub

46         System.out.println("SimpleProxy somethingElse "+arg); 47  proxied.somethingElse(arg); 48  } 49 

50 } 51 

52 public  class SimpleProxyDemo{ 53     

54     public static void consumer(Interface iface){ 55  iface.doSomething(); 56         iface.somethingElse("hello world"); 57  } 58     

59     public static void main(String[] args){ 60         consumer(new RealObject()); 61         System.out.println("/*****************************/"); 62         consumer(new SimpleProxy(new RealObject())); 63  } 64 }

 运行结果如下:

1 doSomething 2 somethingElsehello world 3 /*****************************/

4 SimpleProxy doSomething 5 doSomething 6 SimpleProxy somethingElse hello world 7 somethingElsehello world

五、Java动态代理

  Java的动态代理比代理的思想更向前迈进了一步,因为它可以动态地创建代理并动态地处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作揭示调用的类型并确定相应的对策。 

接下来我们来看一下Java动态代理的例子:

 1  interface Interface {  2 

 3     void doSomething();  4 

 5     void somethingElse(String arg);  6 }  7 

 8 class RealObject implements Interface {  9 

10  @Override 11     public void doSomething() { 12         // TODO Auto-generated method stub

13         System.out.println("doSomething"); 14  } 15 

16  @Override 17     public void somethingElse(String arg) { 18         // TODO Auto-generated method stub

19         System.out.println("somethingElse" + arg); 20  } 21 

22 } 23 

24 //动态代理类

25 class DynamicProxyHandler implements InvocationHandler{ 26 

27     private Object proxied; 28     

29     public DynamicProxyHandler(Object proxied) { 30         // TODO Auto-generated constructor stub

31         this.proxied = proxied; 32  } 33 

34  @Override 35     public Object invoke(Object proxy, Method method, Object[] args) 36             throws Throwable { 37         // TODO Auto-generated method stub

38         System.out.println("****proxy: " + proxy.getClass()+

39                 ", method: "+method+ ", args: "+ args); 40         

41         if(args != null){ 42             for (Object arg : args) { 43                 System.out.println("  "+ arg); 44  } 45  } 46         

47         return method.invoke(proxied, args); 48  } 49 } 50 

51 class SimpleDynamicProxy{ 52     

53     public static void consumer(Interface iface){ 54  iface.doSomething(); 55         iface.somethingElse("hello world"); 56  } 57     

58     public static void main(String[] args){ 59         RealObject real = new RealObject(); 60  consumer(real); 61         

62         System.out.println("/*******************************/"); 63         

64         Interface proxy = (Interface)Proxy.newProxyInstance( 65                 Interface.class.getClassLoader(), 66                 new Class[]{Interface.class}, 67                 new DynamicProxyHandler(real)); 68         

69  consumer(proxy); 70         

71  } 72     

73 }

运行结果如下:

1 doSomething 2 somethingElsehello world 3 /*******************************/

4 ****proxy: class com.sun.proxy.$Proxy0, method: public abstract void Interface.doSomething(), args: null

5 doSomething 6 ****proxy: class com.sun.proxy.$Proxy0, method: public abstract void Interface.somethingElse(java.lang.String), args: [Ljava.lang.Object;@756095fc 7  hello world 8 somethingElsehello world

   通过调用静态方法Proxy.newProxyInstance()可以创建动态代理。这个方法需要得到一个类加载器(你通常可以从已经被加载的对象中获取其类加载器,然后传递给它),一个你希望该代理实现的接口列表(不是类或者抽象类),以及InvocationHandler接口的一个实现。动态代理可以将所有调用重定向到调用处理器,因此通常会向调用处理器的构造器传递一个“实际”对象的引用,从而使得调用处理器执行其中介任务时,可以将请求转发。

   invoke()方法传递进来了代理对象,以防你需要区分请求的来源,但是在许多情况下,你并不关心这一点。然而,在invoke()内部,在代理上调用方法时需要格外小心,因为接口的调用将被重定向为对代理对象的调用。

  通常,你会执行被代理的操作,然后使用Method.invoke()将请求转发给 被代理对象,并传入必需的参数。这初看起来可能有些受限,就像你只能执行泛化操作一样。但是,你可以通过传递其他的参数,来过滤某些方法的调用。

你可能感兴趣的:(java动态代理)