1. jdk 动态代理使用
要求:jdk 动态代理要求被代理的对象至少实现一个接口。
代理逻辑:
jdk 会先产生一个继承 Proxy
类,并实现所有目标对象 implement 接口的代理类,然后调用代理类的构造方法(参数类型为 InvocationHandler)。代理类会:
- 复写目标对象所有 implement 接口的所有方法,
- 还会对 Object 类中的
equals
,toString
,hashCode
方法进行复写
这里就是说,代理对象也会对equals
,toString
,hashCode
这些方法进行代理。所以,如果 InvocationHandler 中只是简单的反射调用 target 对象的所有方法,那么代理对象.hashCode()
实际返回的是 target 对象的 hashCode (spring aop 没有对这些方法进行代理,就是因为其 InvocationHandler 实现类JdkDynamicAopProxy
的 invoke 中对这些方法从做了判断,没有反射调用 target 对象的方法)
这些方法内部都是使用 InvocationHandler 对象
的 invoke(Object targetObj, Method method, Object[] params)
方法,从而实现代理。
如下例子,接口为 Animal, 实现类为 Cat, InvocationHandler 为 MyDynamicProxy
// Animal.java
public interface Animal {
void eat();
void sayHello(String word);
}
// Cat.jjava
public class Cat implements Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sayHello(String word) {
System.out.println(word);
}
@Override
public String toString() {
System.out.println("我是小花猫");
return "我是小花猫";
}
}
最终生成的代理类为 sun.proxy.$Proxy0
package com.sun.proxy;
import com2.test.proxy.Animal;
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 Animal {
private static Method m0; // Object 的 hashCode()
private static Method m1; // Object 的 equals()
private static Method m2; // Object 的 toString()
private static Method m3; // Animal 的 eat()
private static Method m4; // Animal 接口的 sayHello()
// 构造器
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
// Object 的方法
public final boolean equals(Object var1) throws {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
}
// 实现接口的方法
public final void sayHello(String var1) throws {
super.h.invoke(this, m4, new Object[]{var1});
}
// 实现接口的方法
public final void eat() throws {
super.h.invoke(this, m3, (Object[])null);
}
// Object 的方法
public final String toString() throws {
return (String)super.h.invoke(this, m2, (Object[])null);
}
// Object 的方法
public final int hashCode() throws {
return (Integer)super.h.invoke(this, m0, (Object[])null);
}
static {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m4 = Class.forName("com2.test.proxy.Animal").getMethod("sayHello", Class.forName("java.lang.String"));
m3 = Class.forName("com2.test.proxy.Animal").getMethod("eat");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
}
}
看到,代理类代理执行方法,是先通过静态代码块获取代理的方法对象(Method
),然后在自己实现的方法内,调用 InvocationHandler#invoke()
。 invoke() 方法则是通过反射调用 target 对象的方法进行代理
查看示例代码
2. jdk 动态代理类的生成
动态代理类的生成,需要客户端调用代码:
Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this
);
源码中,生成代理对象分为三步:
- (1)用目标对象的 ClassLoader, 实现的 interface 列表 生成代理类 Class
- (2)获取代理类的一个参数,且参数类型为 InvocationHandler 的构造函数
- (3)反射调用构造函数生成代理对象
// Proxy.java
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
// 1. 根据 ClassLoader、interfaces 生成代理类 Class
Class<?> cl = getProxyClass0(loader, intfs);
// 2. 从代理类 Class 中获取参数类型是 InvocationHandler 的构造方法
final Constructor<?> cons = cl.getConstructor(constructorParams);
// 3. 通过构造方法生成代理类对象
return cons.newInstance(new Object[]{h});
}
后两步很简单, 关键是如何生成代理类。生成过程在 ProxyClassFactory
的 apply()
中
- (1)生成代理类的包名:
遍历所有接口,如果目标对象 implement 了一个非 public 接口,则代理类包名和这个接口包名相同;如果都是 public 接口,代理类包名为com.sun.proxy
- (2)生成代理类类名:
$Proxy
加数字
数字是一个static final AtomicLong
- (3)生成代理类二进制数组 (该过程可先忽略,看上面的 class 文件即可)
- (4)将二进制数据用 classLoader 加载进内存
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
// ...
String proxyPkg = null; // (1)生成代理类所在包名
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
// 遍历所有接口,如果目标对象 implement 了一个非 public 接口,则代理类包名和这个接口包名相同
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) {
// com.sun.proxy
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
// (2)代理类类名
long num = nextUniqueNumber.getAndIncrement();
// String proxyClassNamePrefix = "$Proxy"
String proxyName = proxyPkg + proxyClassNamePrefix + num;
// (3)生成代理类二进制数组
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
// (4)将二进制数据用 classLoader 加载进内存
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
}
}