JDK 动态生成的代理对象在调用方法时,为什么总会掉我们实现的InvocationHandler接口里面的invoke方法

查看JDK 动态生成的代理类

首先提供代理接口:

package com.bee.test.spi;


import com.alibaba.dubbo.common.extension.SPI;

@SPI("test")
public interface SpiTest {

	/**
	 * Compile java source code.
	 * 
	 * @param code Java source code
	 * @param classLoader TODO
	 * @return Compiled class
	 */
	public void print(String msg);

}

SpiTest 接口的实现类,即目标对象。此处省略。。。

在生成代理类前加入System.getProperties().put(“sun.misc.ProxyGenerator.saveGeneratedFiles”,“true”); 设置,即在

Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{SpiTest.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                return method.invoke(proxy, args);//proxy 在此处有问题。会发生循环调用,导致栈溢出。 应该调用目标对象
            }
        });

这段代码前加入,才会在生成代理类时候同时将其放入工作空间的目录下,默认是在com\sun\proxy 目录中。
在这里插入图片描述

注意:并不是在你项目的target目录下生成,(这个找了半天硬是没找到),而是在当前的工作空间里。比如用idea 打开的项目,工作空间是xfq_work,项目是xfq-empmall-web.但是生成的是在xfq_work目录下。
在这里插入图片描述

代理类的解析

通过上面生成的$Proxy0.class,用idea打开或者反编译后如下:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.sun.proxy;

import com.bee.test.spi.SpiTest;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

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

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

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

    public final String toString() throws  {
        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 hashCode() throws  {
        try {
            return ((Integer)super.h.invoke(this, m0, (Object[])null)).intValue();
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

	// SpiTest 接口里面的方法
    public final void print(String var1) throws  {
        try {
            super.h.invoke(this, m3, new Object[]{var1}); // 调用我们实现的InvocationHandler接口的invoke方法
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

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

代理类会继承java.lang.reflect.Proxy,并实现传入的接口SpiTest 里面的方法print(). 代码如下:

	// SpiTest 接口里面的方法
    public final void print(String var1) throws  {
        try {
            super.h.invoke(this, m3, new Object[]{var1}); // 调用我们实现的InvocationHandler接口的invoke方法
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

super.h.就是java.lang.reflect.Proxy里面的InvocationHandler类型成员变量。
在这里插入图片描述
至此,我们知道了在代理对象中调用方法时,为什么总会掉我们实现的InvocationHandler接口里面的invoke方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值