栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

2021-10-20

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

2021-10-20

JDK动态代理
      • 代理模式
          • 代理实现方式
        • JDK动态代理实现

代理模式

给某对象提供一个代理对象,通过代理对象可以访问该对象的功能。主要解决通过代理去访问[不能直接访问的对象],例如 租房中介,你可以直接通过中介去了解房东的房源信息,此时中介就可以称为代理。或者通过代理对象对原对象方法增强。

优点:

职责清晰、高扩展性、智能化

缺点

  1. 由于在客户端和真实subject之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。
  2. 实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
代理实现方式
  1. 基于接口的动态代理

    JDK官方提供的Proxy类

    要求是被代理类最少实现一个接口

  2. 基于子类的动态代理

    第三方的CGLib

    要求是被代理类不能用final修饰的类(终类)即被代理的类要求可以作为父类被继承

代理模式不是说非要使用这些技术才能叫做代理模式,代理模式是一种设计模式的思想

JDK动态代理实现

核心

  1. 被代理对象需要实现一个接口
  2. 代理对象需要实现 InvocationHandler 接口,重写invoke方法

代理访问被代理对象的指定方法,实现不直接调用被代理对象执行其方法,或者执行其增强方法而不同修改被代理对象方法代码

原理

给被代理对象实现的接口创建新的实现类(代理类)

// 被代理类实现的接口
public interface Landlord {
    void rent(String name);
}
// 被代理实现类
public class LandlordImpl implements Landlord{

    @Override
    public void rent(String name) {
        System.out.println(name + "房东把房子租给了他!");
    }
}
// 代理类
public class Intermediary implements InvocationHandler {
    private final Object instance;

    public Intermediary(Object instance) {
        this.instance = instance;
    }

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

        // 在这里可以添加方法执行前的增强代码
        System.out.println("代理前执行");
        args[0] = args[0]+ "找到了中介, 中介帮他找到了合适的房东...";
        Object result = method.invoke(instance, args);
        // 在这里可以添加方法执行后的增强代码,但是不能添加输出语句
        System.out.println("代理后执行");
        return result;
    }
}

这里invoke方法中有一个proxy参数

  1. 按理来讲invoke第一个参数是哪一个实例调用此方法,为什么不是this?

  2. 这个proxy参数在这里有什么用?

首先为什么不是this,这里的proxy表示的是实际调用被代理对象方法的代理实例,而在这个类中的this表示的是当前实例,这两个是不同的。

前者是Proxy.newProxyInstance()创建出来的代理对象,后者是辅助前者创建代理对象的实例,是InvocationHandler类型的(是个中介)。

就相当于房东把自己实例告诉中介,中介(this)稍作修饰后保存好,等需要的时候直接用中介保存好的版本(proxy)直接调用里面的方法

其次这个proxy在这里有什么作用?

  • 可以通过反射获取到代理对象的一些信息

  • 可以作为返回值返回,方便接收后继续链式调用

参考:添加链接描述

// 动态代理实现
// 1. 首先要有被代理对象的实例
Landlord landlord = new LandlordImpl();
// 2. 创建代理对象实例,但是代理对象不能直接new创建,通过Proxy类创建
Landlord landlordProxy = (Landlord) Proxy.newProxyInstance(
    // 1. 被代理对象的类加载器(需要反射调用其方法)
    landlord.getClass().getClassLoader(),
    // 2. 被代理对象实现的所有接口,需要利用其接口创建新的代理实例
    landlord.getClass().getInterfaces(),
    // 3. 代理类型实例,需要实现InvocationHandler接口
    new Intermediary(landlord)
);
// 调用通过被代理对象所有接口重新创建的新的代理对象的增强方法
landlordProxy.rent("张三");
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/340717.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号