Java动态代理学习

代理

什么是代理模式

代理模式是程序设计中的一种常见设计模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用,代理对象主要负责为委托对象(真实对象)预处理消息、过滤消息、传递消息给委托类,代理类不现实具体服务,而是利用委托类来完成服务,并将执行结果封装处理。

为什么要用代理

中介隔离:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
开闭原则,增加功能:代理类除了是客户类和委托类的中介之外,我们还可以通过给代理类增加额外的功能来扩展委托类的功能,这样做我们只需要修改代理类而不需要再修改委托类,符合代码设计的开闭原则。代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后对返回结果的处理等。代理类本身并不真正实现服务,而是同过调用委托类的相关方法,来提供特定的服务。真正的业务功能还是由委托类来实现,但是可以在业务功能执行的前后加入一些公共的服务。例如我们想给项目加入缓存、日志这些功能,我们就可以使用代理类来完成,而没必要打开已经封装好的委托类。

动态代理

在程序执行中,使用jdk的反射机制,创建代理类对象,并动态的指定要代理的目标类。动态代理是一种创建Java对象的能力,不用创建类就能创建代理类对象

动态代理类型

动态代理分为JDK动态代理cglib动态代理两类

  • JDK动态代理: 使用Java反射包java.lang.reflect和接口实现动态代理的功能,包下有三个主要类:

    • InvocationHandler接口

      • InvocationHandler是由代理实例的调用处理程序实现的接口 。

      • 每个代理实例都有一个关联的调用处理程序。

      • 当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。

      • InvocationHandler接口只有一个方法 invoke()

      • invoke():表示代理对象要执行的功能代码。代理类要完成的功能就写在invoke()方法中。

    • Method类

      • 表示目标类中的方法
      • 通过Method. invoke()可以执行某个目标类的方法, method. invoke(目标对象,方法的参数)
    • Proxy类

      • 核心的对象,通过静态方法 newProxyInstance()创建代理对象,等同于静态代理中的A a = new A()
  • cglib动态代理:cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。cglib是通过继承目标类来实现的,故要求目标类及其方法不能为final修饰。cglib应用于多种框架,如mybatis,spring等

Java动态代理步骤

  1. 创建接口,定义目标类要完成的功能

  2. 创建目标类实现接口

  3. 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能

  4. 调用目标方法

  5. 增强功能

  6. 使用Proxy类的静态方法,创建代理对象,并把返回值转换成接口类型

Java动态代理样例

  1. 创建接口,定义目标类要完成的功能
public interface ProductSell {
    int getPrice(int price);
}

  1. 创建目标类实现接口
public class ProductSellImpl implements ProductSell {
    @Override
    public int getPrice(int price) {
        System.out.println("商品原价:"+price);
        return price;
    }
}

  1. 创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
public class MySellHandler implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object res ;
        res = method.invoke(target,args);
        System.out.println("开始动态代理,商品价格+15");
        return (int)res+15;
    }
}
  1. 使用Proxy类的静态方法,创建代理对象,并把返回值转换成接口类型
public class MainShop {
    public static void main(String[] args) {
        //创建代理对象,使用Proxy
       // 1.创建目标对象
        ProductSell productSell = new ProductSellImpl();
        //2.创建InvocationHandler对象
        MySellHandler mySellHandler = new MySellHandler(productSell);
        //3.创建代理对象
        ProductSell proxyInstance = (ProductSell) Proxy.newProxyInstance(mySellHandler.getClass().getClassLoader(), productSell.getClass().getInterfaces(), mySellHandler);
        int price = proxyInstance.getPrice(12);
        System.out.println("通过动态代理创建对象:最终价格"+price);
    }
}
  1. 执行代理,查看结果

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值