jdk动态代理分析
从一下三点分析jdk动态原理分析
1、代码示例
2、源码分析,
3、执行流程
一、代码示例
注意jdk动态代理是基于接口的,cglib是基于类的
//被代理类和代理类都要实现的接口
public interface Subject {
void request() throws Exception;
}
//被代理的类
public class RealSubject implements Subject {
public void request() {
System.out.println("RealSubject execute request()");
}
}
//增强类
public class JdkProxySubject implements InvocationHandler {
private RealSubject realSubject;
public JdkProxySubject(RealSubject realSubject) {
this.realSubject = realSubject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object result = null;
try {
//利用反射调用被代理对象的对应方法
result = method.invoke(realSubject, args);//七
} catch (Exception e) {
throw e;
} finally {
System.out.println("after");
}
return result;
}
}
//测试
public class Client {
public static void main(String[] args) throws Exception {
//通过设置参数,将生成的代理类的.class文件保存在本地
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
//通过调用Proxy.newProxyInstance生成代理对象
//方法参数为:1)classLoader 2)要代理的接口 3)代理对象的InvocationHandler
//(通过方法参数也可以看出来,JDK代理只能通过代理接口来来实现动态代理)
Subject subject = (Subject) Proxy.newProxyInstance(Client.class.getClassLoader(),
new Class[]{Subject.class}, new JdkProxySubject(new RealSubject()));//一
//调用代理对象的request方法。
//(根据InvocationHandler接口的定义,可以知道实际调用的是JdkProxySubject里的invoke方法)
subject.request();//五
}
}
运行结果
before
RealSubject execute request()
after
二、源码分析
Proxy.newProxyInstance
去除判断逻辑后的源码
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException {
final Class<?>[] intfs = interfaces.clone();
/*
* Look up or generate the designated proxy class.
*/
//根据提供的接口(在我们的例子中,即Subject接口),生成代理类
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
*/
final Constructor<?> cons = cl.getConstructor(constructorParams);
//调用代理类的构造器,构造器参数为InvocationHandler的接口实现类(在我们的例子中,即JdkProxySubject)
return cons.newInstance(new Object[]{h});//三
}
getProxyClass0(loader, intfs);
去除判断逻辑后的源码
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
// 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
//已经生成过代理类会放到cache里,没有生成过的话,会由ProxyClassFactory创建。
//因此,我们可以直接找到ProxyClassFactory,查看代理类是如何创建的。
return proxyClassCache.get(loader, interfaces);
}
ProxyClassFactory。apply()
去除判断逻辑后的源码
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy";
// next number to use for generation of unique proxy class names
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
//第一步:确定包名,如果没有非public的代理接口,包名使用com.sun.proxy
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
if (proxyPkg == null) {
// if no non-public proxy interfaces, use com.sun.proxy package
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
//第二步:确定类名。(在我们例子中,生成的代理类名为com.sun.proxy.$Proxy0)
/*
* Choose a name for the proxy class to generate.
*/
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
//第三步:根据类名、代理接口等信息,生成代理类。实际上可以理解为生成.class文件。
/*
* Generate the specified proxy class.
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
//第四步:根据生成的.class文件,返回一个代理类Class。此方法为native方法
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
}
}
代理类分析(重点)
public final class $Proxy0 extends Proxy implements Subject {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $Proxy0(InvocationHandler h) throws {
super(h);//通过这句,将invocationHandler实例传给了父类构造器。//四
}
public final boolean equals(Object var1) throws {
try {
return ((Boolean)super.h.invoke(this, m1, new Object[]{var1})).booleanValue();//六
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
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);
}
}
//$Proxy0继承了Proxy,且将InvocationHandler h在构造时传给了Proxy。
//因此,super.h.invoke(this, m3, (Object[])null)其实就是调用的invoker handler的invoke方法。
//也正是像InvocationHandler定义中所说的,【当proxy instance的方法被调用时,方法调用将会委派为invocation handler的invoke方法】。
public final void request() throws Exception {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (Exception | 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)).intValue();
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[]{Class.forName("java.lang.Object")});
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
m3 = Class.forName("proxy.pattern.Subject").getMethod("request", new Class[0]);//二
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
Proxy中InvocationHandler的定义如下
public class Proxy implements java.io.Serializable {
/**
* the invocation handler for this proxy instance.
* @serial
*/
protected InvocationHandler h;
/**
* Constructs a new {@code Proxy} instance from a subclass
* (typically, a dynamic proxy class) with the specified value
* for its invocation handler.
*
* @param h the invocation handler for this proxy instance
*
* @throws NullPointerException if the given invocation handler, {@code h},
* is {@code null}.
*/
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
}
三、执行流程
步骤一、Proxy.newProxyInstance(Client.class.getClassLoader(), new Class[]{Subject.class}, new JdkProxySubject(new RealSubject()));
//创建代理类,传入单个参数,类加载器,接口集合,增强类集合
步骤二、m3 = Class.forName("proxy.pattern.Subject").getMethod("request", new Class[0]);//通过反射机制得到接口方法
步骤三、cons.newInstance(new Object[]{h});//真正的创建代理对象,并且吧增强器对象
步骤四、super(h);通过代理类的构造方法吧增强对象invovationHandler传到Proxy对象里
步骤五、subject.request();调用代理对象的接口实现方法
步骤六、super.h.invoke(this, m3, (Object[])null);//获取增强类调用invoke方法
步骤七、method.invoke(realSubject, args);//通过反射传入被代理对象调用对应的方法

浙公网安备 33010602011771号