基于JDK的动态代理原理

一、动态代理的步骤

        1、先编写公共接口和实现此接口的目标类(被代理类)。

        2、编写实现了InvocationHandler接口的类,在这个类中一般会有接口对象,和一个invoke方法,在invoke中通过接口调用目标类的方法,同时添加自己的方法。

        3、通过newProxyInstance静态方法创建代理类。

// 编写公共接口

package service;


/**
 * 在静态代理中,代理类和目标类都必须实现相同的接口,因为对于客户端来说,
 * 使用代理类就像使用目标类一样,所以二者必须实现相同的接口,具有相同的特性。
 */

public interface OrderService {
    /**
     * 生成订单
     */
    void generate();

    /**
     * 修改订单
     */
    void modify();

    /**
     * 查看订单
     */
    void detail();
}
// 编写实现类(目标类,被代理类)
package service;


public class OrderServiceImpl implements OrderService{
    public void generate() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("订单已经生成");
    }

    @Override
    public void modify() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("订单已经修改");
    }

    @Override
    public void detail() {
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("订单信息如下");
    }

}
// 编写调用处理器,在这里面通过属性调用方法
package service;

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

public class TimeInvocationHandler implements InvocationHandler {
    // 目标对象
    OrderService orderService;

    public TimeInvocationHandler(OrderService orderService) {
        this.orderService = orderService;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Long begin = System.currentTimeMillis();

        // 通过属性调用方法,完成了目标类中的目标方法,其他的都是增强功能
        Object invoke = method.invoke(orderService, args);
        long end = System.currentTimeMillis();
        System.out.println("耗时"+(end-begin)+"毫秒");
        return null;
    }
}
// 测试程序

package client;

import service.OrderService;
import service.OrderServiceImpl;
import service.TimeInvocationHandler;

import java.lang.reflect.Proxy;

public class test {
    public static void main(String[] args) {
        // 创建目标对象
        OrderService orderService = new OrderServiceImpl();

        // 创建代理对象
        OrderService proxyInstance = (OrderService) Proxy.newProxyInstance(orderService.getClass().getClassLoader(),
                orderService.getClass().getInterfaces(),
                new TimeInvocationHandler(orderService));

        // 调用方法
        proxyInstance.generate();
//        proxyInstance.modify();
//        proxyInstance.detail();


    }
}

 二、动态代理源码的简单理解

在借鉴了其他博主的介绍下,只介绍最简单的逻辑理解,即代码 Proxy.newProxyInstance(...)的逻辑。

 简单说就是在底层生成了class文件,我们要获取此calss文件(class对象),然后通过反射得到参数为“调用处理器对象”构造方法,最后通过构造方法实例化对象

底层生成的class文件所对象的类,实现了公共接口并且继承了Proxy。实现是基于代理类必须和被代理类实现同一个接口。继承则是在于调用此对象时,可以调用父类Proxy中的invoke方法。这样只要将相应方法和参数传给父类Proxy的invoke方法就行。

参考:

这些只是我为了好理解,简单地说法,具体内部实现可参考一下两篇文章

(5条消息) 动态代理——JDK动态代理原理&示例解析(图文并茂)_朝花夕拾~~~的博客-CSDN博客

JDK动态代理-超详细源码分析 - 简书 (jianshu.com)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值