JDK动态代理实现

231 阅读2分钟

动态代理机制

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

Interface InvocationHandler

该接口中仅定义了一个方法Object:invoke(Object obj,Method method,Object[] args)。在实际使用时,第一个参数obj一般是指代理类,method是被代理的方法,args为该方法的参数数组。这个抽象方法在代理类中动态实现。

Proxy

  • 该类即为动态代理类
  • Protected Proxy(InvocationHandler h) // 构造函数,用于给内部的h赋值
  • Static Class getProxyClass (ClassLoader loader,Class[] interfaces) // 获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组
  • Static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h) // 返回代理类的一个实例,返回后的代理类可以当作被代理类使用(可使用被代理类的在Subject接口中声明过的方法)
  • Dynamic Proxy // 它是在运行时生成的class,在生成它时你必须提供一组interface给它,然后该class就宣称它实现了这些 interface。你当然可以把该class的实例当作这些interface中的任何一个来用。当然啦,这个Dynamic Proxy其实就是一个Proxy,它不会替你作实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。

示例代码

创建抽象主体接口

/**
 * @ClassName : Subject
 * @Description : 抽象主题接口
 * @Author : feng
 * @Date: 2020-04-17 19:22
 */
public interface Subject {

    void doSomething();

}

创建真实主体接口

/**
 * @ClassName : RealSubject
 * @Description : 真实主题接口
 * @Author : feng
 * @Date: 2020-04-17 19:23
 */
public class RealSubject implements Subject {

    public void doSomething() {
        System.out.println("RealSubject do something");
    }
}

实现InvocationHandler

/**
 * @ClassName : JdkProxy
 * @Description : jdk动态代理
 * @Author : feng
 * @Date: 2020-04-17 09:05
 */
public class JdkProxy implements InvocationHandler {

    private Object target;

    public JdkProxy(Object target){
        this.target = target;
    }

    /**
     * 获取被代理接口实例对象
     * @param <T>
     * @return
     */
    public <T> T getProxy() {
        return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object result = method.invoke(target, args);
        after();
        return result;
    }

    private void before(){
        System.out.println("Do something before");
    }

    private void after(){
        System.out.println("Do something after");
    }

}

测试类

public class JdkProxyTest {

    public static void main(String[] args) {
        Subject subject = new JdkProxy(new RealSubject()).getProxy();
        subject.doSomething();
    }

}

运行结果

Do something before
RealSubject do something
Do something after