静态代理和动态代理学习

使用代理模式有什么作用?

  1. 功能增强

  1. 隐藏真实目标

静态代理

例如 :

  1. 房东只负责收租,中介负责带租客去看房

  1. 厂家负责生产,商铺进行售卖

静态代理是程序执行前就已经设置好的了

缺点 : 需要创建很多代理类和目标类

优点 : 责任分离,可以隐藏真实对象

动态代理

在程序执行之后,使用JDK反射,并动态的指向需要代理的真实目标

可以解决静态代理创建很多代理类的麻烦

JDK动态代理

反射包 java.lang.reflect 里面有三个类

  1. InvocationHandler

创建类,实现这个接口,重写invoke()方法,把原来静态代理中代理类要完成的功能写在里面

  1. Method

执行某个目标类的方法Method.invoke();

  1. Proxy : 创建代理类对象,newProxyInstance();返回值就是地阿里对象

主要方法

InvocationHandler :

    public Object invoke(Object proxy, Method method, Object[] args)
    
    // proxy :生成的代理对象;
    // method:当前调用的真实方法对象;
    // args :当前调用方法的实参;
    
    // 返回:真实方法的返回结果。

Proxy :

    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler hanlder)
    
    // loader :类加载器,一般传递真实对象的类加载器;
    // interfaces:代理类需要实现的接口;
    // handler:代理执行处理器,说人话就是生成代理对象帮你要做什么。
    
    // 返回:创建的代理对象。

cglib动态代理

第三方的工具库,原理是继承,通过继承目标类,子类重写父类中同名的方法,实现功能修改

使用JDK还是cglib?

  1. 如果对象实现了接口,默认使用JDK

  1. 如果对象没有实现接口,必须采用cglib

  1. JDK代理不需要依赖第三方的库,在JDK环境就可以进行代理

  1. cglib必须依赖于cglib的库

  1. JDK动态代理只能为接口创建代理

  1. cglib可以为普通的类也实现代理

JDK动态代理代码例子

售卖USB功能的接口

/**
 * 售卖USB
 */
public interface UsbShell
{
    float shell(int amount);
}

USB工厂批发价85元售卖

/**
 * 目标类 USB 工厂
 */
public class UsbFactory implements UsbShell
{
    /**
     * 一个USB卖85块
     * @param amount 售卖数量
     * @return
     */
    @Override
    public float shell(int amount) {
        System.out.println("目标类");
        return 85.0f;
    }
}

代理类涨价到100元售卖(功能增强)

/**
 * 代理类
 */
public class MyHandler implements InvocationHandler
{
    // 传入进来的对象,就是代理类
    private Object target;

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

    /**
     * @param proxy  生成的代理对象
     * @param method 当前调用的真实方法对象
     * @param args   调用真实方法的参数
     * @return 代理类
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    {
        Object res = null;
        // 等价于 UsbFactory.shell();
        res = method.invoke(target, args);

        // 代理类涨价U盘,功能增强
        Float price = (Float) res;
        price = price + 15;
        res = price;

        System.out.println("代理类");
        return res;
    }
}

顾客进行购买

/**
 * 购买USB
 */
public class Shop
{
    public static void main(String[] args)
    {
        // 1.创建目标对象
        UsbFactory usbFactory = new UsbFactory();

        // 2.创建 InvocationHandler 对象
        MyHandler myHandler = new MyHandler(usbFactory);

        // 3.使用 Proxy 创建代理对象
        UsbShell proxy = (UsbShell) Proxy.newProxyInstance(
                usbFactory.getClass().getClassLoader(), // loader:类加载器,一般传递真实对象的类加载器
                usbFactory.getClass().getInterfaces(), // interfaces:代理类需要实现的接口
                myHandler); // handler:代理执行处理器,说人话就是生成代理对象帮你要做什么

        // 4.执行方法
        float price = proxy.shell(1);
        System.out.println("通过动态代理执行方法" + price);
    }
}

JDK动态代理执行流程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值