代理模式

87 阅读3分钟

静态代理

public class UserControllerProxy implements IUserController {
   private MetricsCollector metricsCollector;
  private UserController userController;

  public UserControllerProxy(UserController userController) {
   this.userController = userController;
  this.metricsCollector = new MetricsCollector();
   }

   @Override
   public void login(String telephone, String password) {
   long startTimestamp = System.currentTimeMillis();

   // 委托
   UserVo userVo = userController.login(telephone, password);

   long endTimeStamp = System.currentTimeMillis();
   long responseTime = endTimeStamp - startTimestamp;
   RequestInfo requestInfo = new RequestInfo("login", responseTime, startTimestamp);
   metricsCollector.recordRequest(requestInfo);
   }

   @Override
   public void register(String telephone, String password) {
   long startTimestamp = System.currentTimeMillis();

   // 委托
   UserVo userVo = userController.register(telephone, password);

   long endTimeStamp = System.currentTimeMillis();
   long responseTime = endTimeStamp - startTimestamp;
   RequestInfo requestInfo = new RequestInfo("register", responseTime, startTimestamp);
   metricsCollector.recordRequest(requestInfo);
   }
  }

动态代理

就是我们不事先为每个原始类编写代理类,而是在运行的时候,动态地创建原始类对应的代理类,然后在系统中用代理类替换掉原始类。

JDK动态代理

定义一个接口

package com.wqq.example.demo.test;

public interface ProductService {

    void addProduct(String name);
}

实现类

package com.wqq.example.demo.test;

/**
 * @ClassName ProductServiceImpl
 * @Description todo
 * @Author wenqiqi090
 * @Date 2021/12/30 7:21 下午
 */
public class ProductServiceImpl implements ProductService{
    @Override
    public void addProduct(String name) {
        System.out.println("正在添加商品");
    }
}

InvocationHandler

`invoke()` 方法有下面三个参数:

1.  **proxy** :动态生成的代理类
2.  **method** : 与代理类对象调用的方法相对应
3.  **args** : 当前 method 方法的参数
package com.wqq.example.demo.test;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @ClassName JdkInvocationHandler
 * @Description todo
 * @Author wenqiqi090
 * @Date 2021/12/30 7:19 下午
 */
public class JdkInvocationHandler implements InvocationHandler {

    private ProductService target;

    public Object getInstance(ProductService target) {

        this.target = target;
        Class clazz = this.target.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);

    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

       // args==11
        System.out.println("begin");
        Object returnValue = method.invoke(target, args);

        System.out.println(returnValue);
        System.out.println("end");

        return returnValue;
    }
}

Test类

package com.wqq.example.demo.test;

import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;

/**
 * @ClassName JdkTest
 * @Description todo
 * @Author wenqiqi090
 * @Date 2021/12/30 7:29 下午
 */
public class JdkTest {

    public static void main(String[] args) throws Exception {

        ProductService productService = new ProductServiceImpl();

        ProductService productServiceProxy = (ProductService) new JdkInvocationHandler().getInstance(productService);
        productServiceProxy.addProduct("phone");

        // 这里我们将jdk生成的代理类输出了出来,方便后面分析使用
        byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0",new Class[]{productService.getClass()});

        FileOutputStream os = new FileOutputStream("Proxy0.class");
        os.write(bytes);
        os.close();
    }

}

调用步骤

  1. begin
  2. 正在添加商品
  3. null
  4. end

生成的代理类

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

import com.wqq.example.demo.test.ProductServiceImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements ProductServiceImpl {
    private static Method m1;
    private static Method m8;
    private static Method m2;
    private static Method m3;
    private static Method m5;
    private static Method m4;
    private static Method m7;
    private static Method m9;
    private static Method m0;
    private static Method m6;

    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 notify() throws  {
        try {
            super.h.invoke(this, m8, (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 void addProduct(String var1) throws  {
        try {
            super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final void wait(long var1) throws InterruptedException {
        try {
            super.h.invoke(this, m5, new Object[]{var1});
        } catch (RuntimeException | InterruptedException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final void wait(long var1, int var3) throws InterruptedException {
        try {
            super.h.invoke(this, m4, new Object[]{var1, var3});
        } catch (RuntimeException | InterruptedException | Error var5) {
            throw var5;
        } catch (Throwable var6) {
            throw new UndeclaredThrowableException(var6);
        }
    }

    public final Class getClass() throws  {
        try {
            return (Class)super.h.invoke(this, m7, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

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

    public final void wait() throws InterruptedException {
        try {
            super.h.invoke(this, m6, (Object[])null);
        } catch (RuntimeException | InterruptedException | 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"));
            m8 = Class.forName("com.wqq.example.demo.test.ProductServiceImpl").getMethod("notify");
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.wqq.example.demo.test.ProductServiceImpl").getMethod("addProduct", Class.forName("java.lang.String"));
            m5 = Class.forName("com.wqq.example.demo.test.ProductServiceImpl").getMethod("wait", Long.TYPE);
            m4 = Class.forName("com.wqq.example.demo.test.ProductServiceImpl").getMethod("wait", Long.TYPE, Integer.TYPE);
            m7 = Class.forName("com.wqq.example.demo.test.ProductServiceImpl").getMethod("getClass");
            m9 = Class.forName("com.wqq.example.demo.test.ProductServiceImpl").getMethod("notifyAll");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m6 = Class.forName("com.wqq.example.demo.test.ProductServiceImpl").getMethod("wait");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}
public final void addProduct(String var1) throws  {
    try {
        super.h.invoke(this, m3, new Object[]{var1});
    } catch (RuntimeException | Error var3) {
        throw var3;
    } catch (Throwable var4) {
        throw new UndeclaredThrowableException(var4);
    }
}

其中h是 JdkInvocationHandler

源码分析

获取代理类

image.png

image.png

动态生成class文件放进jvm内存里 image.png

通过反射生成代理类

image.png