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

  • 相关阅读:
    react 踩坑第一天
    vue-cli+axios+跨域
    vuex 进阶 mapState mapGetter mapActions mapMutations
    vue Bus
    各种html布局
    echarts柱状图设置渐变色
    html设置一个当前时间
    css设置字体渐变色
    C++中指针与引用详解
    go-admin 开源后台管理系统
  • 原文地址:https://www.cnblogs.com/yfyzy/p/4401833.html
Copyright © 2020-2023  润新知