Java动态代理是什么?

本文介绍了Java动态代理的概念,包括动态代理的类和接口、动态代理机制、注意点及源码跟踪。动态代理主要用于创建对象,其核心是类,通过实现接口创建调用处理器,动态生成字节码并由类装载器加载。代理类继承自,实现所代理的接口,调用处理器的invoke方法执行实际操作。动态代理在Spring AOP、MyBatis等框架中有广泛应用。
摘要由CSDN通过智能技术生成

动态代理的类和接口

  • Proxy:动态代理机制的主类,提供一组静态方法为一组接口动态的生成对象和代理类。
// 方法 1: 该方法用于获取指定代理对象所关联的调用处理器
public static InvocationHandler getInvocationHandler(Object proxy) 

// 方法 2:该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
public static Class<?> getProxyClass(ClassLoader loader, 
Class<?>... interfaces)

// 方法 3:该方法用于判断指定类对象是否是一个动态代理类
public static boolean isProxyClass(Class<?> cl) 

// 方法 4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
public static Object newProxyInstance(ClassLoader loader,
 Class<?>[] interfaces,InvocationHandler h)
  • InvocationHandler:调用处理器接口,自定义invokle方法,用于实现对于真正委托类的代理访问。
/**
 该方法负责集中处理动态代理类上的所有方法调用。
 第一个参数既是代理类实例,
 第二个参数是被调用的方法对象
 第三个方法是调用参数。
 调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行
*/
public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable;
  • ClassLoader:类装载器类,将类的字节码装载到Java虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。
    Proxy类与普通类的唯一区别就是其字节码是由JVM在运行时动态生成的而非预存在于任何一个.class文件中。
    每次生成动态代理类对象时都需要指定一个类装载器对象:newProxyInstance()方法第一个参数。

动态代理机制

java动态代理创建对象的过程为如下步骤:

  • 通过实现InvocationHandler接口创建自己的调用处理器
// InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
// 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用
InvocationHandler handler = new InvocationHandlerImpl(..); 
  • 通过为Proxy类指定ClassLoader对象和一组interface来创建动态代理类
// 通过 Proxy 为包括 Interface 接口在内的一组接口动态创建代理类的类对象
Class clazz = Proxy.getProxyClass(classLoader, new Class[] {
    Interface.class, ... }); 
  • 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型
// 通过反射从生成的类对象获得构造函数对象
Constructor constructor = clazz.getConstructor(new Class[] {
    InvocationHandler.class });
  • 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入
// 通过构造函数对象创建动态代理类实例
Interface Proxy = (Interface)constructor.newInstance(new Object[] {
    handler });

为了简化对象创建过程,Proxy类中的newProxyInstance方法封装了2~4,只需两步即可完成代理对象的创建。

// InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
InvocationHandler handler = new InvocationHandlerImpl(..); 

// 通过 Proxy 直接创建动态代理类实例
Interface proxy = (Interface)Proxy.newProxyInstance( classLoader, 
     new Class[] {
    Interface.class }, 
     handler );

动态代理的注意点

  • 包:代理接口是public,则代理类被定义在顶层包(package为空),否则(default),代理类被定义在该接口所在包,
  • 生成的代理类为public final的,不能被继承
  • 类名:格式是$ProxyNN是逐一递增的数字,代表Proxy被第N次动态生成的代理类,要注意对于同一组接口(接口的排列顺序也相同),不会重复创建动态代理类,而是返回一个先前已经创建并缓存了的代理类对象。提高了效率。
  • Proxy类是它的父类,这个规则适用于所有由Proxy创建的动态代理类。(也算是java动态代理的一处缺陷,java不支持多继承,所以无法实现对class的动态代理,只能对于Interface的代理)而且该类还实现了其所代理的一组接口,这就是为什么它能够被安全地类型转换到其所代理的某接口的根本原因。
  • 代理类的根类java.lang.Object中有三个方法也同样会被分派到调用处理器的invoke方法执行,它们是hashCodeequalstoString.

示例代码:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值