JDK动态代理(通俗白话)

首先要明确一点:代理的对象是一件事情!如何理解这句话?举个栗子:我是某一个地区白酒经营的总代理。说白了就是我是一个卖酒的,我代理的是一件事,那就是帮别人卖酒。我从白酒生产厂家那里获得白酒,并把它卖出去,我从中赚取差价。(在生活中只要不是生产商去直接销售,中间商都简称代理,实际上代理指的是某一件具体的事)

        上面说了比较多的废话主要想说明代理是什么?那么代理的关系又是什么呢?其实代理就可以简单理解为是中间商。它不需要亲自去生产制造,只要专心做某一件事就好了。还是白酒,不需要去酿酒,只需要把酒卖出去就好了。而对于卖白酒这件事来说并没有太多约束,假如我是一个地区的白酒总代理,那么卖什么总类的酒对我来说并不用太过在意,因为我只是去卖白酒,不管是卖茅台、五粮液还是二锅头或牛栏山对我本人来说倒是无所谓。

代理有什么用呢?

        还是拿白酒来举例:比如一个消费者想买一瓶二锅头和一瓶五粮液。如果没有代理那么这个消费者就需要去找五粮液的生产厂家,然后从生产厂家那里获得一瓶五粮液。然后再去找二锅头生产厂家,然后从那里买一瓶二锅头。这样一来是非常非常不方便的。那么有了代理之后,这位消费者直接去到代理那里说要买一瓶五粮液和一瓶二锅头。代理直接就从这个厂家那里拿货就好了,只不过需要赚取一点辛苦费。但是对于消费者来说不需要那么麻烦了买这两种酒就很方便。

引申到Java中来说,传统的创建方法都是直接new一个对象出来。如果有两个对象那么代码就需要写两次,要new两遍,代码非常不灵活。

五粮液酒厂类:

 二锅头酒厂类:

 传统方式:

 

以上面的买白酒为例:

        一个消费者需要买一瓶五粮液和一瓶二锅头,那么首先要有一个五粮液酒厂家的类和一个二锅头厂家的类。这两个类中分别都有一个卖白酒的方法sellWine(),在买酒的时候分别将两个酒厂家对象都new出来,然后再调用里面的sellWine()方法。反正都是要去买酒,那么我们可以想象一下,如果有人能够代替你去完成创建对象的操作就好了。也就是说反正我是要买酒,如果我需要买一瓶五粮液那么就有人能给我new一个五粮液酒厂家对象,如果我需要一瓶二锅头那么再给我new一个二锅头厂家对象那就方便很多了。我只要提供白酒厂家的名字(这个厂家必须要先存在),他就能自己去动态的给我创建一个白酒厂家的对象。那么这就是动态代理。需要什么对象这种机制就能动态创建什么对象,同时能调用对象当中的方法执行。还可以将原来的功能再进行扩展。还以买白酒为例,消费者去买一瓶五粮液白酒,代理就创建一个五粮液酒厂对象还能调用这个酒厂类中的卖酒方法sellWine(),从而获得白酒的原厂价格。当拿到原厂价格之后,代理还能对此价格进行额外的处理,比如每瓶酒加价10%之后再卖出去。这就调用了酒厂类中的方法并进行额外的扩展。

那么上面说了这么多JDK动态代理的代码应该怎么写呢?

jdk 动态代理是代理模式的一种实现方式,其只能代理接口。
实现步骤
1 、新建一个接口,作为目标接口
2 、为接口创建一个实现类,是目标类
3 、创建类实现 java.lang.reflect.InvocationHandler 接口,调用目标方法并增加其他功能代码
4 、创建动态代理对象,使用 Proxy.newProxyInstance() 方法,并把返回值强制转为接口类型。
上面四步按照卖白酒的例子来说就是:
1、定义一个接口,这个接口内规定就是代理是一件什么事
public interface SellWine {
  int sell(int amount);
}

2、定义白酒生产厂商,并要实现卖白酒的接口

定义一个茅台厂家

public class MaoTaiSellWineImpl implements SellWine {
  @Override
  public int sell(int amount) {
    int price = amount * 1250;
    return price;
  }
}

定义一个五粮液厂家

public class WuLiangYeSellWineImpl implements SellWine {
  @Override
  public int sell(int amount) {
    int fee = amount * 1000;
    return fee;
  }
}

定义一个二锅头厂家

public class ErGuoTouSellWineImpl implements SellWine {
  @Override
  public int sell(int amount) {
    int fee = amount * 50;
    return fee;
  }
}

3、这一步就好比是一个代理要代理卖白酒这件事,要事先拟定好合同签订协议的过程(每一瓶白酒加价多少等等这些扩招功能)

public class MySellWineInvocationHandler implements InvocationHandler {
  /*
  * 要代理卖白酒这件事,明确要卖谁生产的白酒,代理对象就是白酒生产厂家
  * */
  //让目标对象有代理功能
  private Object target;

  public MySellWineInvocationHandler() {
  }

  public MySellWineInvocationHandler(Object target) {
    this.target = target;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //确定关系,从厂商那里拿酒卖(这里用到的是反射机制)
    Object feeObj = method.invoke(target,args);
    int feeAmount = (int) feeObj;
    //扩展功能,代理卖白酒需要加价获利(每次获利为厂家拿货价的0.05)
    int totalFee = feeAmount + (feeAmount / 20);
    return totalFee;
  }
}

4、拟定好协议之后才真正开始创建一个动态代理对象,开始代理卖白酒这件事

public class WineAgentObjectTest {
  public static void main(String[] args) {
    Object wineSell = null;
    try {
      Class wines = Class.forName("com.feiHuTechnologyCompany.jdkDynamicProxy.wine.impl.ErGuoTouSellWineImpl");
//      Class wines = Class.forName("com.feiHuTechnologyCompany.jdkDynamicProxy.wine.impl.WuLiangYeSellWineImpl");
//      Class wines = Class.forName("com.feiHuTechnologyCompany.jdkDynamicProxy.wine.impl.ErGuoTouSellWineImpl");
      //创建白酒生产厂商对象
      wineSell = wines.newInstance();
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (InstantiationException e) {
      e.printStackTrace();
    }
    String wineName;
    if(wineSell.getClass().getSimpleName().equals("MaoTaiSellWineImpl")){
      wineName = "茅台";
    }else if(wineSell.getClass().getSimpleName().equals("WuLiangYeSellWineImpl")){
      wineName = "五粮液";
    }else{
      wineName = "其他种类";
    }


    //创建调用处理器(展示代理合同,合同内容大致为谁代理了什么事,扩展了什么功能)
    InvocationHandler handler = new MySellWineInvocationHandler(wineSell);

    //创建动态代理对象
    SellWine wo = (SellWine) Proxy.newProxyInstance(
            wineSell.getClass().getClassLoader(),
            wineSell.getClass().getInterfaces(),
            handler
                                                  );

    //代理卖白酒
    int amount = 10;
    int price = wo.sell(amount);
    System.out.println("从我这买"+amount+"瓶"+wineName+"酒需要"+price+"大洋");
  }
}

 传入不同的白酒生产厂商后得到的结果分别如下(顺序是茅台、五粮液、二锅头)

 

 

 可以看到传入的类可以写入配置文件当中,当修改配置文件后就能动态的创建对象并调用方法执行,还可以进行功能的扩展,不需要自己再去new对象。java许多框架都用到了jdk动态代理和反射机制来实现对象的创建。

(一个尚未工作,在code路上疯狂踩坑并努力爬起的小学生。上述表述如有误,请批评指正!谢谢!)

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值