开篇
- 日常阅读开源的代码框架的时候经常会到Proxy动态代理的应用场景,抽空研究一下。
- 借助于Proxy的demo和反编译动态代理代码来分析调用过程。
- 借助于Proxy的动态代理类的源码分析下动态类的生成过程。
Proxy应用场景
package com.sunboy;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import sun.misc.ProxyGenerator;
public class ViewProxyClass {
public static void main(String[] args) throws Exception {
Game gamePlayer = new GamePalyer("张三");
ClassLoader classLoader = gamePlayer.getClass().getClassLoader();
Class<?>[] interfaces = gamePlayer.getClass().getInterfaces();
// 生成动态代理的基本操作
Game proxy = (Game) Proxy.newProxyInstance(classLoader, interfaces, new GameInvocation(gamePlayer));
proxy.paly();
// 生成动态代理的源码的调试方法
byte[] bts = ProxyGenerator.generateProxyClass("$GameProxy", interfaces);
FileOutputStream fos = new FileOutputStream(new File("D:/tmp/$GameProxy.class"));
fos.write(bts);
fos.flush();
fos.close();
}
// 接口的定义
interface Game {
public void paly();
}
// 接口的实现
static class GamePalyer implements Game {
private String name;
public GamePalyer(String name) {
this.name = name;
}
@Override
public void paly() {
System.out.println(this.name + " playing ...");
}
}
// 动态代理的封装对象
static class GameInvocation implements InvocationHandler {
private Game target;
public GameInvocation(Game target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(target + "被代理");
method.invoke(this.target, args);
return proxy;
}
}
}
- Proxy动态代理类基于Interface维度的,被代理类需要实现Interface,如案例中提到的GamePalyer类实现Game接口。
- Proxy的动态代理封装类需要实现InvocationHandler接口,如案例中的GameInvocation对象。
- 动态代理类的生成通过Proxy.newProxyInstance来实现。动态代理类的代码是由Proxy的接口动态定义生成,可以通过ProxyGenerator.generateProxyClass("$GameProxy", interfaces)生成代理类并保存到class文件后反编译后观察。
- InvocationHandler的第一个参数Object是指动态生成的代理类,第二个参数是被代理的方法,第三方参数是动态入参。
Proxy动态代理类
import com.sunboy.ViewProxyClass.Game;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $GameProxy extends Proxy implements Game {
private static Method m1;
private static Method m2;
private static Method m3;
private static Method m0;
public $GameProxy(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 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 paly() throws {
try {
super.h.invoke(this, m3, (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"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.sunboy.ViewProxyClass$Game").getMethod("paly");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
public class Proxy implements java.io.Serializable {
private static final long serialVersionUID = -2222568056686623797L;
protected InvocationHandler h;
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
}
- 动态代理类GameProxy继承Proxy并implement被代理接口(如案例中的Game)。
- 动态代理类GameProxy的构造函数$GameProxy(InvocationHandler var1)的参数为InvocationHandler 对象,并传给父类Proxy。
- 动态代理类GameProxy通过Class.forName来加载被代理接口,并通过getMethod获取被代理的Method。
- 动态代理类重写了被代理的Method,并通过 super.h.invoke()调用InvocationHandler的invoke方法。
- 动态代理类核心就是重载被代理的方法,并在重载的方法内部调用代理对象Invocation的invoke方法。代理的实现代码在Invocation里面
动态代理类工厂
public class Proxy implements java.io.Serializable {
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
private static final String proxyClassNamePrefix = "$Proxy";
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
// 检查被代理的Interface的合法性
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
Class<?> interfaceClass = null;
try {
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
// 检查package的合法性
String proxyPkg = null; // package to define proxy class in
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
for (Class<?> intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.getName();
int n = name.lastIndexOf('.');
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
// 1、生成动态代理的类
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
// 2、加载动态代理的类
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
}
}
- ProxyGenerator.generateProxyClass()负责生成动态代理类。
- defineClass0负责加载新生成的动态代理类并返回。
- ProxyClassFactory负责动态生成代理类的工厂。
网友评论