`
H_eaven
  • 浏览: 31365 次
  • 性别: Icon_minigender_1
  • 来自: 鲨堡
文章分类
社区版块
存档分类
最新评论

代理与动态代理

阅读更多
代理模式:
 
   public interface Interface {
      void doSomething();
      void somethingElse(String arg);
  }
  public class RealSubject implements Interface {
     public void doSomething() {
          System.out.println("realSubject.doSomething()...");
      }
    public void somethingElse(String arg) {
         System.out.println("realSubject.somethingElse(" + arg + " )...");

    }
}
public class SimpleProxy implements Interface {
   private Interface real;
   public SimpleProxy(Interface obj) {
      this.real = obj;
  }
   public void doSomething() {
      System.out.println("simpleProxy--before");
      real.doSomething();
}
   public void somethingElse(String arg) {
     System.out.println("simpleProxy--before");
     real.somethingElse(arg);
} 
}
public class Main {
   public static void main(String[] args) {
       Interface obj = new RealSubject();
       Interface simpleProxy  = new SimpleProxy(obj);
       simpleProxy.doSomething();
       simpleProxy.somethingElse("testString");
   }
}

这个基本上是最简单的代理模式实现了.
对Interface接口方法的调用,都被SimpleProxy截获了.


动态代理:
能够在运行时实现接口但在编译时不用声明其实现接口的特殊类.////
Java的动态代理比代理的思想又向前了一步.因为它可以动态的创建代理并动态地处理对所有代理的方法调用.在动态代理上所做的所有调用都会被重定向到单一的调用处理器上.(Thinking in Java)
SimpleProxy在编译期已经存在,但动态代理可以在运行期生成代理类,及代理实例.

用动态代理改写上面的例子:
    public class InvocationHandlerImpl implements InvocationHandler {
        private Object target;
        public InvocationHandlerImpl(Object obj) {
           this.target = obj;
}
       public Object invoke(Object proxy,Method method,Object[] args) throws Throwable {
           System.out.println("methodName:" + method.getName());
           System.out.println("proxy:" + proxy.getClass().getName());
           if (args != null) {
              for(Object o : args) {
                  System.out.println(o);
              }
          }
          return method.invoke(target,args);  //1:转发请求
}
} 
  public class Main {
      public static void main(String[] args) {
           Interface real = new RealSubject();
           Interface proxy = (Interface)Proxy.newProxyInstance(Interface.class.getClassLoader(),new Class[]{Interface.class},new InvocationHandlerImpl(real));
          proxy.doSomething();
          proxy.somethingElse("proxyString");
      }
 }


此时可以对多个接口进行方法调用的拦截,AOP的实现.
普通代理模式可能要针对一个接口实现一个代理.
动态代理则只需要编写一个调用处理器的实现类,根据传入的代理接口列表动态生成代理类和代理实例.


   public interface OtherInterface {
      public void play();
   } 

在这里再给出一个接口,但是对这个接口没有默认实现类.
改写上面的调用处理器实现类:

     public class InvocationHandlerImpl2 implements InvocationHandler {
        private Object target;
        public InvocationHandlerImpl2(Object obj) {
           this.target = obj;
}
       public Object invoke(Object proxy,Method method,Object[] args) throws Throwable {
           System.out.println("methodName:" + method.getName());
           System.out.println("proxy:" + proxy.getClass().getName());
           if ("play".equals(method.getName())) {
              System.out.println("invoke OtherInterface.play method!");
         return null;
          }
           if (args != null) {
              for(Object o : args) {
                  System.out.println(o);
              }
          }
          return method.invoke(target,args);
}
} 
public class Main {
      public static void main(String[] args) {
           Interface real = new RealSubject();
           Object proxyObject = Proxy.newProxyInstance(Interface.class.getClassLoader(),new Class[]{Interface.class,OtherInterface.class},new InvocationHandlerImpl2(real));
          Interface proxy = (Interface)proxyObject;
          proxy.doSomething();
          proxy.somethingElse("proxyString");
          OtherInterface otherProxy = (OtherInterface)proxyObject;
          otherProxy.play();
      }
 }


可能的结果:
  methodName:doSomething
proxy:$Proxy0
realSubject.doSomething()...
methodName:somethingElse
proxy:$Proxy0
proxyString
realSubject.somethingElse(proxyString )...
methodName:play
proxy:$Proxy0
invoke OtherInterface.play method!



调用处理器截获对OtherInterface.play()方法的调用.作出处理后并返回,因为没有RealSubject,因些也无法向真实对象进行请求转发.
从外部看:好像Interface的实例经过调用处理器的处理,他又实现了另外一个接口.

现再调用处理器的作用不再只是进行对方法截获进行处理,请求转发;
它实际在做一种实现工作,
(只是进行对方法截获进行处理,而没有进行请求转发就可以看成一种重写了)

再从另个一个角度看,此时的调用处理器不只是进行代理,而还有适配器的形,但可能完全没有适配器的目的,因为Interface和OtherInterface完全没有关系.但可以从一个Interface的实例转型为一个OtherInterface.

甚至在调用Proxy.newProxyInstance()方法生成代理实例的时候,不传入RealSubject对象,那么调用处理器完全冲当代理接口的实现类,而没有了请求转发这一步骤.
不过这完全不是代理的初衷了!
注:1处的转发调用是当有传入RealSubject对象时才可以调用,如果传入null,则要进行单独处理.

动态的意思:1.可以横行为一组接口实现横切逻辑.
          2.可以在运行时动态实现一个接口实例,Proxy$X为接口的实现类.






分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics