一. 样例代码
1. Animal接口
public interface Animal {
public void eat();
public void run();
}
2. Cat
Cat 实现了 Animal 接口;
public class Cat implements Animal {
@Override
public void eat() {
System.out.println("cat eat---");
}
@Override
public void run() {
System.out.println("cat run---");
}
/**
* 此处的 hunt() 是 Cat 类自己的方法
* 代理类 Proxy 实现的是 Animal 接口,Proxy 没有 hunt() 方法
*/
public void hunt() {
System.out.println("cat hunt---");
}
}
3. MyInvocationHandler
MyInvocationHandler 需要实现 InvocationHandler 接口;
public class MyInvocationHandler implements InvocationHandler {
private Animal animal;
/**
* 构造 MyInvocationHandler 对象的时候
* 需要将被代理对象传进来作为私有属性
* @param animal 被代理对象
*/
public MyInvocationHandler(Animal animal) {
this.animal = animal;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("----代理对象前置工作执行");
Object result = method.invoke(animal, args);
System.out.println("----代理对象后置工作执行");
return result;
}
}
4. Test01
public class Test01 {
public static void main(String[] args) {
// 这一句是生成代理类的class文件,会在当前项目路径 com.sun.proxy 包下生成代理类
// System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
// 1. 需要被代理的对象为 cat 对象
Cat cat = new Cat();
// 2. 创建出 InvocationHandler 对象
MyInvocationHandler myInvocationHandler = new MyInvocationHandler(cat);
// 3. 创建出代理对象,代理对象 proxy 是 Animal 接口的实现类
Animal proxy = (Animal)Proxy.newProxyInstance(cat.getClass().getClassLoader(),
cat.getClass().getInterfaces(),
myInvocationHandler);
// 4. 执行 proxy 的各种方法
proxy.eat();
proxy.run();
}
}
执行结果如下:
----代理对象前置工作执行
cat eat---
----代理对象后置工作执行
----代理对象前置工作执行
cat run---
----代理对象后置工作执行
二. 代理类
1. 生成的代理类
1、jdk 的动态代理只有被代理对象实现了接口的情况下才能工作,因为代理对象 $Proxy0 需要继承 Proxy 类,并且代理对象会实现接口;如果被代理对象没有实现接口,不能使用 jdk 动态代理;
2、代理类 $proxy0 聚合了 InvocationHandler 对象;
3、代理类 $proxy0 的方法实际上执行的都是 invocationHandler.invoke();
package com.sun.proxy;
import com.zengqiang.dynamicjdk.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 m1;
private static Method m3;
private static Method m4;
private static Method m2;
private static Method m0;
public $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 run() throws {
try {
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final void eat() throws {
try {
super.h.invoke(this, m4, (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("com.zengqiang.dynamicjdk.Animal").getMethod("run");
m4 = Class.forName("com.zengqiang.dynamicjdk.Animal").getMethod("eat");
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());
}
}
}
2. InvocationHandler
InvocationHandler 接口只有一个抽象方法,如下:
public interface InvocationHandler {
/**
* proxy: 代理类对象
* method: 方法
* args: 方法执行参数
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
3. Proxy
在生成代理类对象时,我们会调用 Proxy.newProxyInstance(),我们简单看下该方法;
1、生成代理类的 Class 对象;
2、根据 Class 对象和构造方法构造出代理对象;
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h) {
Objects.requireNonNull(h);
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
// 1. 生成代理类的 Class 对象
Class<?> cl = getProxyClass0(loader, intfs);
try {
if (sm != null) {
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
// constructorParams = InvocationHandler.class
// 获取代理类的构造方法,选择参数为InvocationHandler类型的构造方法
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
// 2. 根据构造方法和参数 invocationHandler 构造出代理类对象
return cons.newInstance(new Object[]{h});
} catch (Exception e) {
throw e;
}
}
Class<?> cl = getProxyClass0(loader, intfs) 中,生成并加载 Class 对象和 Proxy 的静态内部类 ProxyClassFactory 有关,我们简单看下 ProxyClassFactory 做了啥,了解即可;
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) {
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) {
throw ex;
}
//保证 interfaces 接口集合内全部都是接口
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
//保证 interfaces 接口集合内没有重复接口
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
// 生成的代理类的包名
String proxyPkg = null;
// 生成的代理类 访问修饰符:public final ....
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
// 检查接口集合内的接口,看看有没有某个接口它的访问修饰符不是 public 的
// 如果有哪个接口修饰符不是 public 的,那么我们生成代理类 class 就必须和它在一个包下
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) {
//如果接口没有非 public 的,那么使用默认的包名
//可以看到默认是在 com.sun.proxy 包下
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
//获取唯一编号
long num = nextUniqueNumber.getAndIncrement();
//代理类名称 = 包名 + $proxy + 数字
String proxyName = proxyPkg + proxyClassNamePrefix + num;
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
// 使用加载器加载这个二进制字节码文件到 jvm,并且返回此代理类 Class
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
}