终于从内存中把JDK动态代理生成的类内容捞出来了

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

上一篇:这300G的Java资料是我师傅当年给我的,免费分享给大家

下一篇:这200G的Java实战资料是我师傅当年教我的第二

链接 | 木叶之荣

来源 | blog.csdn.net/zknxx/article/details/77919332

public interface PersonInter {
 
    String test(String str);
}

接着就是我们想的要生成的JDK代理类源码的代码:

public class JdkProxySourceClass {
 
  public static void writeClassToDisk(String path){
 
    byte[] classFile = ProxyGenerator.generateProxyClass("$proxy4", new Class[]{PersonInter.class});
    FileOutputStream fos = null;
    try {
      fos = new FileOutputStream(path);
      fos.write(classFile);
      fos.flush();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }finally{
      if(fos != null){
        try {
          fos.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
 
    @Test  
    public void testGenerateProxyClass() {
      JdkProxySourceClass.writeClassToDisk("D:/$Proxy4.class");
    }
}

重要的就是这一句话:byte[] classFile = ProxyGenerator.generateProxyClass("$proxy4", new Class[]{PersonInter.class});

OK接下来我们用反编译工具看一下生成的代理类源码:

import com.zkn.newlearn.gof.proxyhandler.PersonInter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
 
public final class Proxy4 extends Proxy
  implements PersonInter
{
  private static Method m1;
  private static Method m2;
  private static Method m3;
  private static Method m0;
 
  public Proxy4(InvocationHandler paramInvocationHandler)
    throws 
  {
    super(paramInvocationHandler);
  }
 
  public final boolean equals(Object paramObject)
    throws 
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
 
  public final String toString()
    throws 
  {
    try
    {
      return ((String)this.h.invoke(this, m2, null));
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
 
  public final String test(String paramString)
    throws 
  {
    try
    {
      return ((String)this.h.invoke(this, m3, new Object[] { paramString }));
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
 
  public final int hashCode()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
 
  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]);
      m3 = Class.forName("com.zkn.newlearn.gof.proxyhandler.PersonInter").getMethod("test", new Class[] { Class.forName("java.lang.String") });
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
}

从反编译出来的源码中我们可以看到在静态代码块中得到了equals、toString、hashCode和PersonInter接口中test方法的Method对象。当我们调用PersonInter中的test方法的时候:

public final String test(String paramString)
    throws
  {
    try
    {
      return ((String)this.h.invoke(this, m3, new Object[] { paramString }));
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

其实是调用了InvocationHandler中的invoke方法,并传入了之前获取到的对应的Method和参数。在这里也简单的说一下为什么JDK的动态代理只能代理接口不能代理类,请注意看我们所得到的代理类的源码,注意看这一句:public final class Proxy4 extends Proxy implements PersonInter。生成的代理类默认继承了Proxy这个类,而java中又是单继承的,所以这里只能代理接口,不能代理类了。就像枚举类,不能继承别的枚举类一样。

说句题外话,springCloud技术交流群正式成立,坑位有限,欢迎进入

猜你喜欢

1、终于见识到12306 的架构到底有多“牛逼”?

2、介绍9款MySQL常见的图形化工具,第三款我用了10年

3、快速搭建ELK日志分析系统

4、终于见识到12306 的架构到底有多“牛逼”?

5、史上最全的Nginx配置参数中文说明

6、Mac版:IntelliJ IDEA常用快捷键

7、2019年10月全国程序员工资统计,一半以上的职位5个月没招到人。

8、经验:那些年,我在大学接过的外包项目

强烈推荐一位大佬的公众号

好文章,我在看❤️

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java提供了一种动态生成的机制,称为Java动态代理。Java动态代理是一种实现AOP(面向切面编程)的方式,它可以在运行时生成一个代理,该代理实现了指定接口,并将方法调用委托给指定的处理器。 动态代理有两种实现方式:JDK动态代理和CGlib动态代理JDK动态代理只能代理实现了接口的,而CGlib动态代理可以代理任何,但是它需要依赖第三方库。 下面是一个使用JDK动态代理生成的示例代码: ``` import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class DynamicProxy implements InvocationHandler { private Object target; public DynamicProxy(Object target) { this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before method invocation"); Object result = method.invoke(target, args); System.out.println("After method invocation"); return result; } public static void main(String[] args) { HelloWorld helloWorld = new HelloWorldImpl(); DynamicProxy dynamicProxy = new DynamicProxy(helloWorld); HelloWorld helloWorldProxy = (HelloWorld) Proxy.newProxyInstance( HelloWorld.class.getClassLoader(), new Class[] { HelloWorld.class }, dynamicProxy); helloWorldProxy.sayHello(); } } interface HelloWorld { void sayHello(); } class HelloWorldImpl implements HelloWorld { public void sayHello() { System.out.println("Hello, world!"); } } ``` 在这个示例代码,我们使用JDK动态代理实现了一个HelloWorld接口的实例。我们首先实现了InvocationHandler接口,并在invoke方法添加了一些前置和后置处理逻辑。然后,我们使用Proxy.newProxyInstance方法创建了一个代理的实例,并将其强制转换为HelloWorld接口型。最后,我们通过调用代理对象的sayHello方法来触发代理的invoke方法。 当我们运行这个示例代码时,它会输出以下内容: ``` Before method invocation Hello, world! After method invocation ``` 这表明代理对象成功地拦截了方法调用,并执行了我们添加的前置和后置处理逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值