手写JDK动态代理

手写JDK动态代理

1、动态代理概述

概述

  • JAVA动态代理与静态代理相对,静态代理是在编译期就已经确定代理类和真实类的关系,并且生成代理类的。而动态代理是在运行期利用JVM的反射机制生成代理类,这里是直接生成类的字节码,然后通过类加载器载入JAVA虚拟机执行。现在主流的JAVA动态代理技术的实现有两种:一种是JDK自带的,就是我们所说的JDK动态代理,另一种是开源社区的一个开源项目CGLIB。本文主要对JDK动态代理做讨论。

  • JDK动态代理的实现是在运行时,根据一组接口定义,使用Proxy、InvocationHandler等工具类去生成一个代理类和代理类实例。

    JDK动态代理的类关系模型和静态代理看起来差不多。也是需要一个或一组接口来定义行为规范。需要一个代理类来实现接口。区别是没有真实类,因为动态代理就是要解决在不知道真实类的情况下依然能够使用代理模式的问题。

在这里插入图片描述

分类

  • JDK的动态代理: 与被代理的类必须实现相同的接口
  • CGLIB: 继承

动态代理几个重要的参数

  • ClassLoader loader: 被代理对象的类加载器

  • Class<?>[] interfaces:接口中的使用方法。

  • InvocationHandler: 处理,加强方法 【invoke()方法

2、手写动态代理

共同实现的接口

package com.qiumin.proxy;

/**
 * @author qiumin
 * @classname Service
 * @Description love code
 * @date 2022-06-06 21:36
 */
public interface Service {

    /**
     * 接口方法
     * */
    void order() throws Throwable;

}

被代理的类

package com.qiumin.proxy;

/**
 * @author qiumin
 * @classname orderService
 * @Description love code
 * @date 2022-06-06 21:36
 */
public class orderService implements Service{


    /**
     * 方法
     * */
    public void order() {
        System.out.println("《订单编号1000101》");
    }

}

自己的MyExtJdkInvocationHandler接口,与InvocationHandler几乎一样

package com.qiumin.proxy;

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

/**
 * @author qiumin
 * @classname MyJdkIN
 * @Description love code
 * @date 2022-06-06 21:29
 */
public interface MyExtJdkInvocationHandler {

  
    Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable;

}

MyJdkInvocationHandler实现MyExtJdkInvocationHandler

package com.qiumin.proxy;

import java.lang.reflect.Method;

/**
 * @author qiumin
 * @classname MyJdkInvocationHandler
 * @Description love code
 * @date 2022-06-06 21:34
 */
public class MyJdkInvocationHandler implements MyExtJdkInvocationHandler{

    /**
     * 被代理的目标对象
     * */
    private Object target;

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

    /**
     * 加强被代理类的方法
     * */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("正在生成订单中......");
        method.invoke(target,args);
        System.out.println("生成订单完打印票据......");
        return null;
    }
}

手写内存中创建的代理类

package com.qiumin.proxy;

import java.lang.reflect.Method;

/**
 * @author qiumin
 * @classname MyProxy
 * @Description love code
 * @date 2022-06-06 21:41
 */
public class MyProxy implements Service{

    /**
     * 处理类
     * */
    private MyJdkInvocationHandler h;

    public MyProxy(MyJdkInvocationHandler h) {
        this.h = h;
    }

    /**
     * 
     * 回调加强方法
     * */
    public void order() throws Throwable {
        //反射获取接口中的方法
        Method method = Service.class.getMethod("order",new Class[]{});
        this.h.invoke(this,method,null);
    }
}

测试

package com.qiumin.proxy;

/**
 * @author qiumin
 * @classname TestProxy
 * @Description love code
 * @date 2022-06-06 21:47
 */
public class TestProxy {
    public static void main(String[] args) throws Throwable {
        //new出MyProxy的对象,将自己的InvocationHandler传进去
        MyProxy myProxy = new MyProxy(new MyJdkInvocationHandler(new orderService()));
        //执行方法
        myProxy.order();
    }
}

3、总结

总结

  • 使用Java程序语言组装.java 源代码,获取实现的接口反射获取。【上面是固定的代理类,使用该方法扩展性强】
  • 用Java程序语言将.java 文件编译生成字节码文件.class ,相当于命令行输入javac。
  • 使用classloader技术将生成的class文件加载到内存中即java虚拟机中,这样才可以执行。
  • 以上就是 Proxy.newProxyInstance()底层的原理

qiumin

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值