JDK动态代理

Posted cwhan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JDK动态代理相关的知识,希望对你有一定的参考价值。

记录下jdk动态代理

一个小白,记录学习遇到的坑

最近正在学习框架,初步了解了下什么是动态代理,记录下来,方便以后复习和修改。

首先代理是啥意思?

个人理解:

我们网购时,在淘宝、京东等平台上购买某件商品后,如果我们不满意,我们是不是可以退款?这就是起到一个代理的作用。

代理的作用

1、通俗的来讲,起到一个控制和增强的作用。

  • 控制:上面的网购可以解释。
  • 增强:可以理解为中间商赚差价。

代理的分类

分为静态代理和动态代理
下面说个例子来讲讲静态代理

静态代理

我们先定义一个U盘的接口

package com.han.usb;

public interface Usb {
    float usbSell(int amount);
}

下面有个制作U盘的厂家,制作u盘。

package com.han.factory;

import com.han.usb.Usb;

public  class UsbFactory implements Usb {
    public float usbSell(int amount) {
        float price=85.0f;
        System.out.println("厂家出厂:"+price);
        return price;
    }
}

下面在创建个代理商。厂家通过这个代理商去联系更多的人,提高收入。
代理商也要吃饭是不是,所以啊这个代理商就赚了亿点点钱,并且还对
顾客说我们已经给了一张优惠卷。

package com.han.Tao;


import com.han.factory.UsbFactory;
import com.han.usb.Usb;

public class Taoproxy implements Usb {

    @Override
    public float usbSell(int amount) {
        UsbFactory usbFactory=new UsbFactory();
        float price=usbFactory.usbSell(amount);
       price = (float) (price+25.0);
        System.out.println("商家给你一个优惠卷,优惠了5快");
        return price;
    }
}

今天,小王看中了这个U盘,就找这个代理商买。

package com.han.customer;

import com.han.Tao.Taoproxy;
import com.han.usb.Usb;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class CustomerShop {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Taoproxy taoproxy=new Taoproxy();
//        float price=taoproxy.usbSell(1);

       Method method = Usb.class.getMethod("usbSell",int.class);
//        int
//        java.lang.Integer
//        System.out.println(int.class.getName());
//        System.out.println(Integer.class.getName());
       float price= (float) method.invoke(taoproxy,1);
       System.out.println("真好,真便宜,最后只花了"+price);

    }

}

买完后,美滋滋!!!

技术图片


这就是一个简单的静态例子,那么这么做的好处是什么了?

  • 假如你的手里有个class文件,你完全不能改动其中的内容,但是这里面的功能不能实现你目前的业务,这时我们就可以通过代理来实现。

哈哈,这个例子我也不知道准不准确,我就继续编下去哈!

改动一个还好,我们只需要手动写几个代理类,但是如果改动100个了。哈哈,我回吐。

就没有什么办法吗? 有办法呀,什么办法了? 就是动态代理


动态代理

我目前只学了jdk动态代理,小声比比。

所谓的动态代理就是不能手动写代理商,交个jvm去动态生成。我们只需要写清楚我们所需要的功能。

那么怎么来实现动态代理了?

  • 我们要实现一个接口InvocationHandler和创建一个代理(代理商)对象

我也没有完全搞明白是怎么创建出来的代理,今天先记录下来,以后在来补充。


先来实现这个接口

package com.han.Tao;

import com.han.usb.Usb;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {
    public Usb target;
    public MyInvocationHandler(Usb target) {
        this.target=target;
    }


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //

      float price= (float) method.invoke(target,args);
        price=price+30.0f;

        System.out.println("商家给你优惠卷");
        return price;
    }
}

解释:
实现这个接口就是要重写这个invoke方法,这个方法的参数解释
下面的参数解释仅仅在我目前的理解下做出的解释,错误重重!!!

  • proxy:个人认为就是创建的代理对象
  • method:显而易见就是我们需要调用的方法
  • args:传入的参数,用在调用method方法时传入的参数
  • target:就是你要代理的目标对象,也就是厂家

好,我们需要处理的业务逻辑代理已经完成了

下面再来创建代理类Proxy

创建代理类用到Proxy类中的一个静态方法,

   public static Object newProxyInstance(ClassLoader loader,
     Class<?>[] interfaces, InvocationHandler h) 

眨眼一看,我的妈呀,这都是啥?
我是晕,不知道您了?

来解释下参数:

  • loader :类加载,加载一个类的字节码文件
  • interfaces: 类实现的接口(可能有多个接口)信息
  • h :我猜,这个就是proxy和invocationHandler连接起来的关键

这也就说明了JDK动态代理是需要有接口的

类加载没有了解过,勿喷啊!!!

 package com.han.customer;

import com.han.Tao.MyInvocationHandler;
import com.han.factory.UsbFactory;
import com.han.usb.Usb;

import java.lang.reflect.Proxy;

public class MyProxy {

    public static void main(String[] args) {

        UsbFactory factory = new UsbFactory();
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(factory);
        Usb proxy = (Usb) Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), myInvocationHandler);
        float price = proxy.usbSell(1);
        System.out.println("真便宜,只用了"+price);
    }
}

proxy.usbSell(1)执行到这儿时,会自动跳转到method.invoke(target,args),执行该方法。

我猜啊
这里的usbSell通过某种方式传给了method参数
而1则传给了args参数


今天先记录到这儿,勿喷啊,小白一个,我会努力的!!!










以上是关于JDK动态代理的主要内容,如果未能解决你的问题,请参考以下文章

JDK动态代理CGLIB动态代理

JDK动态代理CGLIB动态代理

(java反射-JDK动态代理)+CGLIB动态代理

JDK动态代理与Cglib动态代理

JDK动态代理与CGLib动态代理

代理模式(静态代理jdk动态代理CGLib动态代理)