StaticProxy 和 DynamicProxy

静态代理类:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的class文件已经存在。

动态代理类:在程序运行时,运用反射机制动态创建而成。动态代理类的字节码在程序运行时由java反射机制动态生成,无需程序员手工编写源代码。

动态代理类提供软件系统的可扩展性,java反射机制可以生成任意类型的动态代理类。

java.lang.reflect中的Proxy类和InvocationHandler接口提供了生成动态代理类功能

动态实现Foo接口的动态代理类实例:

  • 方式一
    • InvocationHandler handler = new MyInvocationHandler(…);//创建InvocationHandler对象
    • Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(),new Class[]{Foo.class})//创建动态代理类
    • Foo foo = (Foo)proxyClass.getConstructor(new Class[]{InvocationHandler.class}).newInstance(new Object[]{handler});//创建动态代理类的实例
  • 方式二
    • InvocationHandler handler = new MyInvocationHandler();//创建InvocationHandl对象
    • Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[]{Foo.class},handler);//直接创建动态代理类的实例

由Proxy类的静态方法创建的动态代理类具有以下特点:

动态代理类是public、final和非抽象类型的;
动态代理类继承了java.lang.reflect.Proxy类;
动态代理类的名字以“$Proxy”开头;
动态代理类实现getProxyClass()和newProxyInstance()方法中参数interfaces指定的所有接口;

静态代理和动态代理实例链接 实例有一丢丢差别,但是概念比较清楚链接二

以下是ibm的笔记:

  • 1,java.lang.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象.Proxy的静态方法
    • static InvocationHandler getInvocationHandler(Object proxy)
    • static Class getProxyClass(ClassLoader loader,Class[] interfaces)
    • static boolean isProxyClass(class clazz)
    • static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler handler)
  • 2,java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问.InvocationHandler的核心方法
    • Object invoke(Object proxy, Method method, Object[] args)// 该方法负责集中处理动态代理类上的所有方法调用。第一个参数既是代理类实例,第二个参数是被调用的方法对象.第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托类实例上发射执行
  • 3,java.lang.ClassLoader:这是类装载器类,负责将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy 静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,它与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中.

如何使用java动态代理,步骤如下:

通过实现 InvocationHandler 接口创建自己的调用处理器;
通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

动态代理对象创建过程

// InvocationHandlerImpl 实现了 InvocationHandler接口,并能实现方法调用从代理类到委托类的分派转发
// 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用
InvocationHandler handler = new InvocationHandlerImpl(..); 

// 通过 Proxy 为包括 Interface 接口在内的一组接口动态创建代理类的类对象
Class clazz = Proxy.getProxyClass(classLoader, new Class[] { Interface.class, ... }); 

// 通过反射从生成的类对象获得构造函数对象
Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class }); 

// 通过构造函数对象创建动态代理类实例
Interface Proxy = (Interface)constructor.newInstance(new Object[] { handler });

简化的动态代理对象创建过程

// InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
InvocationHandler handler = new InvocationHandlerImpl(..); 

// 通过 Proxy 直接创建动态代理类实例
Interface proxy = (Interface)Proxy.newProxyInstance( classLoader, 
 new Class[] { Interface.class }, 
 handler );

TODO (ibm教程)

特点 代码 实现推演

序列化TODO

blogjava

链接

链接