JDK动态代理源码简析

本文详细解析了如何使用Java的JDK动态代理创建代理对象,通过InvocationHandler中介,代理Fly类实例的方法调用。重点讲解了为何代理能代理接口并演示了关键代码和流程图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

核心类

左边是jdk类,右边是demo的类

其中 Proxy0 是动态生成的一个类,我拷贝出来的

image-20220317160551693

Proxy0 --聚合–> InvocationHandler --聚合–> Plane

所以在调用 Proxy0 的方法时,就能通过 invocationHandler 分配给 Plane

核心代码

public class FlyMain {
    public static void main(String[] args) {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        //InvocationHandler nullProxyHandler = new FlyTimeCountProxy(null);
        InvocationHandler birdProxyHandler = new TimeCountHandler(new Bird());
        InvocationHandler planeProxyHandler = new TimeCountHandler(new Plane());
        Object birdProxy = Proxy.newProxyInstance(FlyMain.class.getClassLoader(), new Class[]{Fly.class}, birdProxyHandler);
        Object planeProxy = Proxy.newProxyInstance(FlyMain.class.getClassLoader(), new Class[]{Fly.class}, planeProxyHandler);
        ((Fly)birdProxy).fly();
        ((Fly)birdProxy).flyDistance();
        System.out.println("\n");
        ((Fly)planeProxy).fly();
        ((Fly)planeProxy).flyDistance();
    }
}
public class TimeCountHandler implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println(proxy.getClass());
        System.out.println(method.getName());
        System.out.println("fly begin ...");
        Object invoke = method.invoke(target, args);
        System.out.println("fly end ...");
        return invoke;
    }
}
package com.xyy.stu.java.core.proxy.flydemo;

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

/**
 * @Author xu_yuanyang
 * @Date 2022/3/17 2:29 下午
 * @Version 1.0
 */
public final class Proxy0 extends Proxy implements Fly {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m4;
    private static Method m0;

    public Proxy0(InvocationHandler var1)  {
        super(var1);
    }

    public final boolean equals(Object var1)  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void fly()  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final String toString() throws  UndeclaredThrowableException{
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int flyDistance() throws  UndeclaredThrowableException{
        try {
            return (Integer)super.h.invoke(this, m4, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode()  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m3 = Class.forName("com.xyy.stu.java.core.proxy.flydemo.Fly").getMethod("fly");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m4 = Class.forName("com.xyy.stu.java.core.proxy.flydemo.Fly").getMethod("flyDistance");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

核心流程时序图

https://www.processon.com/diagraming/6232e14a637689082f02a21d

image-20220317153857455

FAQ

  1. 为什么JDK动态代理对象能代理目标对象

    代理对象和目标对象都实现了相同的接口

    代理对象包含了 InvocationHandler,其实现类一般聚合了被代理对象

  2. 为什么动态代理能代理接口的所有方法

    因为代理类的所有接口实现的方法,都是通过 调用 invocation.invoke 方法, 方法Method是其中一个参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值