java动态代理使用介绍

简单介绍如何使用java动态代理,及稍微进一步介绍基本实现原理

  • 基本用法
// 声明接口
public interface ClientService {
    String echo();
}
// 具体实现类
public class ClientServiceImpl implements ClientService {
    @Override
    public String echo() {
        return "Echo from client!";
    }
}
// 定义拦截回调方法
public class MyInvocationHandler implements InvocationHandler {
    private Object target;
    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //此处进行切面...
        Object result = method.invoke(target, args);
        //此处进行切面...
        return result;
    }
}
// 动态代理使用
public class ProxyTest {
    public static void main(String[] args) {
        ClientService clientService = new ClientServiceImpl();
        MyInvocationHandler myInvocationHandler = new MyInvocationHandler(clientService);
        ClientService proxyService = (ClientService) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), clientService.getClass().getInterfaces(), myInvocationHandler);
        proxyService.echo();
    }
}
  • 基本原理

通过Proxy类生成接口的代理类(Proxy#newProxyInstance()),在调用接口方法的时候,该代理类会调用InvocationHandler的实现类即MyInvocationHandlerinvoke方法,invoke方法内部通过反射去调实现类的具体方法,完成动态代理。
生成的动态代理类示意图如下所示:

public final class $Proxy0 extends Proxy implements ClientService {
    private static Method m3;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

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

    static {
        try {
            m3 = Class.forName("com.lsr.proxy.jdk.ClientService").getMethod("echo");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}
  • 代理类生成主要流程

Proxy#newProxyInstance()
--->Proxy#getProxyClass0()
--->Proxy.proxyClassCache#get()
--->supplier#get()
--->Proxy.ProxyClassFactory#apply()
--->sun.misc.ProxyGenerator#generateProxyClass()
--->Proxy#defineClass0()

ProxyGenerator#generateProxyClass()内部会根据实现类的接口去生成代理类的字节码

  • 如何查看生成的代理类
public class ProxyTest {
    public static void main(String[] args) {
        makeProxyClass();
    }

    public static void makeProxyClass() {
        // 生成ClientServiceImpl代理类字节码
        byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", ClientServiceImpl.class.getInterfaces());
        // 输出到文件中供查看
        makeFile("E:\\workspace\\school\\src\\main\\java\\com\\lsr\\proxy\\jdk\\TestProxy.class", classFile);
    }

    public static void makeFile(String path, byte[] classFile) {
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(path);
            out.write(classFile);
            out.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

你可能感兴趣的:(java动态代理使用介绍)