JDK如何实现动态代理
定义接口与需要被代理的类
/**
* 实现类
*/
class TargetImpl implements TargetService {
@Override
public void sayHello() {
System.out.println("hello world");
}
}
/**
* 需要被代理的接口
*/
public interface TargetService {
/**
* 用于jdk代理,必须要定义接口
*/
void sayHello();
}
如何使用jdk提供的动态代理
/**
* 对代理的类做增强作用
*/
class MyInvokerHandlerProxy implements InvocationHandler {
private Object target;
/**
* 构造方法
*
* @param target 目标对象
*/
public MyInvokerHandlerProxy(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 在目标对象的方法执行之前简单的打印一下
System.out.println("------------------before------------------");
// 执行目标对象的方法
Object result = method.invoke(target, args);
// 在目标对象的方法执行之后简单的打印一下
System.out.println("-------------------after------------------");
return result;
}
/**
* 获取目标对象的代理对象。参数this代表着将增强类传入了Proxy
*
* @return 代理对象
*/
public Object getProxy() {
return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
target.getClass().getInterfaces(), this);
}
}
分析jdk的Proxy类
直接进入Proxy的源代码,非必要代码直接省略
Object Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h){
/*
* Look up or generate the designated proxy class.
*/
Class<?> cl = getProxyClass0(loader, intfs);
final Constructor<?> cons = cl.getConstructor(constructorParams);
return cons.newInstance(new Object[]{h});
}
返回的是一个Object对象,三个参数,loader用于jdk生成字节码后加载到jvm。interfaces由于jdk动态代理必须声明接口,在jdk动态代理的实现类上必然实现该接口。h能够进行增强,并且通过反射调用target的方法。
获取class对象(上面代码里面有非常重要的注释,寻找或是生成指定的代理类的class对象),找到Constructor,之后通过反射返回代理的类的实例。
继续分析获取class对象的方法
public class Proxy implements java.io.Serializable{
/**
* a cache of proxy classes
*/
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
// If the proxy class defined by the given loader implementing
// the given interfaces exists, this will simply return the cached copy;
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
}
}
这里具有迷惑性,jdk注释详细的去解释了这个方法。做了相当多的封装并且加入了cache,注释中已经提到了生成class使用的是ProxyClassFactory。需要有其它的时间来分析WeakCache。
继续进入ProxyClassFactory
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
}
贴出了最重要的步骤。但是ProxyGenerator.generateProxyClass()没有办法看到源代码,defineClass0()是一个native方法,不过通过命名能够看懂这个两个方法主要是做了什么事情,首先生成代理类的字节码,之后加载字节码并返回class对象。ProxyGenerator 这个类能够去openJDK中去看,大概就是通过操作字节码,生成代理类的二进制文件。
分析到这里,其实jdk已经干完了所有事情,但是还是没有办法看到整个代理类是怎么运行的。下面是openJDK 中ProxyGenerator生成字节码后反编译的类。
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package .demo.wangjq.base.designpattern;
import demo.wangjq.base.designpattern.TargetService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class Service$Proxy0 extends Proxy implements TargetService {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public Service$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 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("demo.wangjq.base.designpattern.TargetService").getMethod("sayHello");
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());
}
}
}
下面给出main方法
public static void main(String[] args) {
TargetImpl targetImpl = new TargetImpl ();
MyInvokerHandlerProxy myInvokerHandlerProxy = new MyInvokerHandlerProxy(targetImpl );
/**
* 获取代理后的对象。
*/
TargetService targetService = (TargetService ) myInvokerHandlerProxy.getProxy();
targetService.sayHello();
}
结合上面的 Service$Proxy字节码生成的代理类。能够分析出uml和执行流程。执行流程: main方法中的targetService.sayHello()-> super.h.invoke(this, m3, (Object[])null)-> MyInvokerHandlerProxy.invoke();
在代理类中,继承Proxy,实现了代理类执行的时候是调用了Proxy的InvokerHandler成员变量的invoke,而InvokerHandler实现类是传入到Proxy的MyInvokerHandlerProxy。java无法多继承这也是为什么jdk代理必须要有接口。
UML

以上就是JDK动态代理的所有分析

浙公网安备 33010602011771号