• 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参数


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

  • 相关阅读:
    ubuntu安装gradle
    ubuntu文件查找
    接口服务flask的负载均衡部署
    区块链节点网络的nginx转发部署
    typescript检查包之间是否有循环依赖
    shiro对事务的影响
    防止xss(脚本攻击)的方法之过滤器
    Mysql批量更新速度慢的解决方案
    springBoot的三种启动方式
    mybatis的注解开发之三种动态sql
  • 原文地址:https://www.cnblogs.com/cwhan/p/12989709.html
Copyright © 2020-2023  润新知