Java动态代理

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

一、代理模式的定义

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

二、优点

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

三、模式结构

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

四、UML示意图

 

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

 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()将请求转发给 被代理对象,并传入必需的参数。这初看起来可能有些受限,就像你只能执行泛化操作一样。但是,你可以通过传递其他的参数,来过滤某些方法的调用。

posted @ 2015-04-08 11:26  风走了,雨停了  阅读(2622)  评论(1编辑  收藏  举报