【Spring -- 10 jdk 代理(Proxy)】

 JDK 动态代理生成的代理对象的源码

假设我们有一个 HelloService 接口和它的实现类 HelloServiceImpl:

public interface HelloService {
    void sayHello();
}

public class HelloServiceImpl implements HelloService {
    @Override
    public void sayHello() {
        System.out.println("Hello from HelloServiceImpl!");
    }
}

然后我们使用 JDK 动态代理创建 HelloService 的代理对象:

InvocationHandler handler = (proxy, method, args) -> {
    System.out.println("Before method invocation");
    method.invoke(new HelloServiceImpl(), args);
    System.out.println("After method invocation");
    return null;
};

HelloService proxy = (HelloService) Proxy.newProxyInstance(
    HelloService.class.getClassLoader(),
    new Class[]{HelloService.class},
    handler
);

proxy.sayHello();

我们可以使用反编译工具查看 JDK 动态生成的代理对象的源码:

public final class $Proxy0 extends Proxy implements HelloService {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;

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

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

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

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

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

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
            m3 = Class.forName("com.example.HelloService").getMethod("sayHello", new Class[0]);
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

从生成的代理类源码可以看出:

  1. 代理类名为 $Proxy0,继承了 Proxy 类并实现了 HelloService 接口。
  2. 代理类持有一个 InvocationHandler 实例 h,所有方法调用最终会委托给这个 InvocationHandler
  3. 代理类重写了 equals()toString()hashCode()等 Object 类的方法。
  4. 代理类重写了 HelloService 接口中的 sayHello() 方法。
  5. 代理类在静态初始化块中缓存了一些方法引用,用于提高方法调用的性能。

总之,JDK 动态代理生成的代理类是一个实现了目标接口的 Proxy 子类,它将所有方法调用委托给了 InvocationHandler 实现类,从而实现了动态代理的功能。

注意

  • 限制:代理增强是借助多态来实现,因此成员变量、静态方法、final 方法均不能通过代理实现
  • 前 16 次反射性能较低
  • public Object invoke(Object obj, Object... args)
        throws IllegalAccessException, IllegalArgumentException,
               InvocationTargetException {
        if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Reflection.getCallerClass();
            checkAccess(caller, clazz, obj, modifiers);
        }
        return invoke0(obj, args);
    }
    
    private native Object invoke0(Object obj, Object[] args)
        throws IllegalArgumentException, InvocationTargetException {
        // JVM 调用逻辑
    }
  • 第 17 次调用会生成代理类,invoke() 方法优化为非反射调用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值