美文网首页
关于Java动态代理你知道多少?

关于Java动态代理你知道多少?

作者: 平凡的柚子 | 来源:发表于2021-01-30 15:55 被阅读0次

JDK version: 1.8

动态代理中所说的“动态”, 是针对使用Java代码实际编写了代理类的“静态”代理而言的, 它的优势不在于省去了编写代理类那一点编码工作量,
而是实现了可以在原始类和接口还未知的时候, 就确定代理类的代理行为,当代理类与原始类脱离直接联系后, 就可以很灵活地重用于不同的应用场景之中。

  • 目前Java开发包中包含了对动态代理的支持, 但是其实现只支持对接口的的实现。其实现主要通过 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口。
  • Proxy 类主要用来获取动态代理对象, InvocationHandler 接口用来约束调用者实现。
  • 动态代理是很多框架和技术的基础, spring 的 AOP 实现就是基于动态代理实现的。

Proxy类
Proxy 提供用于创建动态代理类实例的静态方法, 它还是与之创建的所有动态代理类的超类。
介绍一下 Proxy 类中最常用的方法 java.lang.reflect.Proxy#newProxyInstance,

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {
    ... return cons.newInstance(new Object[]{h});
    ...
}

该方法返回动态代理类实例. 该方法有三个参数

  • loader: the class loader to define the proxy class. 与原始类的类加载器一致
  • interfaces: the list of interfaces for the proxy class to implement. 原始类实现的接口
  • h: InvocationHandler 实例, 动态代理类实例会调用 InvocationHandler 实例的 invoke 方法

InvocationHandler接口
InvocationHandler 接口中只有一个方法.

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;

该方法有三个参数

  • proxy: 动态代理类的实例
  • method: 原始类的 Method 实例
  • args: 被代理 Method 需要的参数

下面通过编写一个简单地动态代理类举例说明:

public class DomainProxyTest {

    interface IGreet {

        void sayHello();

        void sayHi();
    }

    static class Greet implements IGreet {

        @Override
        public void sayHello() {
            System.out.println("Hello World!");
        }

        @Override
        public void sayHi() {
            System.out.println("Hi there!");
        }
    }

    static class DynamicProxy implements java.lang.reflect.InvocationHandler {

        Object originalObj;

        Object bind(Object originalObj) {
            this.originalObj = originalObj;
            return java.lang.reflect.Proxy
                .newProxyInstance(originalObj.getClass().getClassLoader(), originalObj.getClass().getInterfaces(), this);
        }

        @Override
        public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args) throws Throwable {
            System.out.println("welcome!");
            return method.invoke(originalObj, args);
        }
    }

    public static void main(String[] args) {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        IGreet greet = (IGreet) new DynamicProxy().bind(new Greet());
        greet.sayHello();
        greet.sayHi();
    }
}

编译 Java 文件:

javac DomainProxyTest.java

** 执行 class 文件:**

发现生成了一个名称为 $Proxy0.class 的文件, 该文件就是 Java 动态生成的代理类. 反编译看一下其内容:

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

final class $Proxy0 extends Proxy implements IGreet {
    private static Method m1;
    private static Method m3;
    private static Method m4;
    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)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

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

    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);
        } 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("DomainProxyTest$IGreet").getMethod("sayHello");
            m4 = Class.forName("DomainProxyTest$IGreet").getMethod("sayHi");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

代码逻辑很简单, 呼应了文章上面对动态代理的描述.


最新2020整理收集的一些高频面试题(都整理成文档),有很多干货,包含mysql,netty,spring,线程,spring cloud、jvm、源码、算法等详细讲解,也有详细的学习规划图,面试题整理等,需要获取这些内容的朋友请加Q君样:11604713672

相关文章

  • 关于Java动态代理你知道多少?

    JDK version: 1.8 动态代理中所说的“动态”, 是针对使用Java代码实际编写了代理类的“静态”代理...

  • android基础_02类加载器

    参考文章 : 深入理解Java类加载器(ClassLoader) 一、动态代理关于类加载器 : 1.1 在看动态代...

  • 关于日程管理你知道多少呢?

    在时间管理的课堂上,我学习到一个很棒的内容。 2008年北京高考的作文题目是一个小故事: “在课堂上,老师拿了一个...

  • 【产品】关于项目管理你知道多少?

    项目管理是产品经理需要掌握的能力之一,本文结合项目管理理论与工作实践 ,输出对项目管理的认知、总结~分享出来,一起...

  • Java基础系列-静态代理和动态代理

    原创文章,转载请标注出处:《Java基础系列-静态代理和动态代理》 1、动态代理(Dynamic Proxy) 代...

  • 性能分析利器arthas

    What arthas 是什么 是Alibaba开源的Java诊断工具,在线排查问题,无需重启;动态跟踪Java代...

  • Java动态代理研究

    浅说动态代理 关于java的代理模式,此处不过多讲解。所谓代理模式是指客户端并不直接调用实际的对象,而是通过调用代...

  • Java代理

    前言 Java代理大致可以分为静态代理(static proxy),动态代理(dynamic proxy)。所谓代...

  • Java 动态代理

    前言 关于动态代理 JDK动态代理 CGLIB动态代理 区别 java动态代理是利用反射机制生成一个实现代理接口的...

  • 个人知识管理你知道多少?

    今天学习了个人知识管理,个人知识管理的形式为:1.知识卡片 2.读书笔记 3.文章写作 4.博客转载 5.日志分享...

网友评论

      本文标题:关于Java动态代理你知道多少?

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