美文网首页
Java 静态代理、动态代理以及反射的关系

Java 静态代理、动态代理以及反射的关系

作者: 放开那个BUG | 来源:发表于2022-03-19 00:34 被阅读0次

1、前言

今天技术分享时,有人分享了 Springboot 应用中事务失败的例子,如类中有 A、B 两个方法,B 用 @Transaction 注解标识,但是在 A 中调用 B 方法时 B 方法的事务不会起作用。原因是调用 A 方法时不会走代理类的切片,然后说到了动态代理、反射等知识。至于这里的详细原因,下次专门开一篇文章分享,进行我想捋清楚的时反射和动态代理的关系。

我们都知道反射可以获取一个对象的所以信息,包括字段、方法等,也可以直接获得该类的 Method 对象,直接 invoke 调用累对象的方法,类似于这样。反射的原理我们不讲,就讲这个用法。

        Class<?> clazz = Q1_reverseList.class;
        Q1_reverseList q1_reverseList = (Q1_reverseList) clazz.newInstance();
        clazz.getMethod("aa").invoke(q1_reverseList);

那么动态代理与反射又有什么关系呢?其实主要的关系在于生成的代理类调用被代理类(原对象)的方法那块,其他真的没了。可以看看👇这个生成的代理类。

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

    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 void cook() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void dealWithFoot() throws  {
        try {
            super.h.invoke(this, m4, (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);
        }
    }

    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.company.ICook").getMethod("cook", new Class[0]);
            m4 = Class.forName("com.company.ICook").getMethod("dealWithFoot", 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());
        }
    }
}

当调用 cook() 方法时,是调用 InvocationHandler 实现类的 invoke 方法,而此方法就是通过反射 invoke 被代理类的方法来调用目标方法。

说到这里,我们讨论了一个最简单的需求。假设一个类有很多方法,如果想为这个类所有的方法增加一个计时功能,那么思路肯定是在方法调用前记录一个 startTime,调用结束后记录一个 endTime,然后相减就是耗时。怎样才能不重复写代码?

开始我想到用静态代理,但是问题是我得实现你所有的方法,然后在方法前后重复写计时。而且想不到不重复写的思路。

而用动态代理,我只需要在 InvocationHandler 实现类的 invoke 方法中写上计时逻辑,然后在中间调用目标方法即可,非常简单。运行结果如下图:


结果
结果

相关文章

  • java反射和动态代理

    java动态代理Proxy.newProxyInstance 详解java代理机制(静态代理、动态代理)以及使用场景

  • Java 静态代理、动态代理以及反射的关系

    1、前言 今天技术分享时,有人分享了 Springboot 应用中事务失败的例子,如类中有 A、B 两个方法,B ...

  • java代理模式2_动态代理_jdk

    动态代理 相对于静态代理,动态代理在创建代理对象上更加的灵活,动态代理类的字节码在程序运行时,由java反射机制动...

  • java代理模式2.2_动态代理_cglib

    动态代理 相对于静态代理,动态代理在创建代理对象上更加的灵活,动态代理类的字节码在程序运行时,由java反射机制动...

  • Proxy - 代理模式

    注意:全文是基于Java来描述和实现的!代理模式的实现有很多种方法:静态代理,动态代理(又分为反射实现的动态代理,...

  • 浅谈Java和SAP ABAP的静态代理和动态代理,以及ABAP

    文章目录 Java的静态代理 静态代理的优缺点 ABAP的静态代理 Spring AOP的动态代理 JDK动态代理...

  • Java基础:反射

    反射注解动态代理相关阅读 Java基础:类加载器 Java基础:反射 Java基础:注解 Java基础:动态代理 ...

  • 安卓反射和动态代理的应用

    提纲 java反射基础 反射在Android中的应用 Java动态代理 动态代理在Android的应用 java反...

  • Java 代理

    静态代理 动态代理 动态代理, 日志切片使用反射获得方法 动态代理, 自定义注解(对注解的方法,使用动态代理添加切...

  • Java动态代理从入门到原理再到实战

    目录 前言 什么是动态代理,和静态代理有什么区别 Java动态代理的简单使用 Java动态代理的原理解读 动态代理...

网友评论

      本文标题:Java 静态代理、动态代理以及反射的关系

      本文链接:https://www.haomeiwen.com/subject/lgpwdrtx.html