JDK动态代理
public interface ClothesFactory {
void makeClothes();
}
public class ClothesFactoryImpl implements ClothesFactory {
@Override
public void makeClothes() {
System.out.println("I make clothes!");
}
}
public Object getProxyInstance(ClothesFactory factory) {
//获取被代理类的1.类加载器 2.接口类 3.InvocationHandler实现类的invoke方法。通过反射
return Proxy.newProxyInstance(factory.getClass().getClassLoader(), factory.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("fire");
method.invoke(factory, args);
return null;
}
});
}
@Test
public void proxyTest() {
ClothesFactoryImpl factory = new ClothesFactoryImpl();
ClothesFactory proxyInstance = (ClothesFactory) getProxyInstance(factory);
proxyInstance.makeClothes();
}
// fire
// I make clothes!
小结
- 直观的感受就是先获取到了实际被代理接口的
method
,将method
作为参数传入到invoke
方法,然后在method.invoke
前面和后面写逻辑
疑问
Proxy.newProxyInstance
是如何返回一个被代理接口的实例?
- 代理实现中如何获取到了被代理接口的
method
?
原理
java.lang.reflect.Proxy.ProxyClassFactory
是java.lang.reflect.Proxy
的内部类
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
* 生成一个.class文件, 反编译之后是一个继承自Proxy, 并实现被代理接口的类, 增强方法InvocationHandler做为其中的成员域
*/
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
/*
* native方法, 执行类加载机制, 返回这个java.lang.Class对象, 最后通过newInstance来创建代理对象, InvocationHandler对象作为构造函数的
* 参数
*/
return defineClass0(loader, proxyName,
proxyClassFile, 0, proxyClassFile.length);
......
}
}
@Test
public void defineClass() throws InvocationTargetException, IllegalAccessException, InstantiationException, NoSuchMethodException, IOException
{
Method defineClass0 = Proxy.class.getDeclaredMethod("defineClass0", new Class[]{ClassLoader.class, String.class, byte[].class, int.class, int.class});
Constructor<Proxy> declaredConstructor = Proxy.class.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
String proxyName = "com.wangfan.proxy.MyProxy";
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, new Class[]{ClothesFactory.class}, Modifier.PUBLIC);
/**
* 将proxyClassFile输出到.class文件
*/
outPutToFile(proxyClassFile);
/**
* JVM类加载, 获取了代理类的java.lang.Class对象, 继承了Proxy, 实现了ClothesFactory接口
*/
Class proxyClass = (Class) defineClass0.invoke(declaredConstructor.newInstance(), ClothesFactory.class.getClassLoader(), proxyName, proxyClassFile, 0, proxyClassFile.length);
//System.out.println(JSON.toJSONString(invoke.getInterfaces()));
/**
* 通过反射获取构造代理类的构造函数,这个构造函数需要一个InvocationHandler对象作为参数
*/
ClothesFactoryImpl clothesFactory = new ClothesFactoryImpl();
Constructor constructor = proxyClass.getConstructor(new Class[]{InvocationHandler.class});
constructor.setAccessible(true);
ClothesFactory factory = (ClothesFactory) constructor.newInstance(new Object[]{(InvocationHandler) (proxy, method, args) -> {
System.out.println("fire");
method.invoke(clothesFactory, args);
return null;
}});
/**
* 执行业务方法
*/
factory.makeShoes();
}
/*
* 输出到文件
*/
private void outPutToFile(byte[] proxyClassFile) throws IOException {
String filepath = "D:\\Code\\Study\\MyProxy.class";
File file = new File(filepath);
if (file.exists()) {
file.delete();
}
FileOutputStream fos = new FileOutputStream(file);
fos.write(proxyClassFile, 0, proxyClassFile.length);
fos.flush();
fos.close();
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.wf.proxy;
import com.wf.proxy.jdk.ClothesFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public class MyProxy extends Proxy implements ClothesFactory {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m4;
private static Method m0;
public MyProxy(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 makeShoes() 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 void makeClothes() throws {
try {
super.h.invoke(this, m4, (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.wf.proxy.jdk.ClothesFactory").getMethod("makeShoes");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m4 = Class.forName("com.wf.proxy.jdk.ClothesFactory").getMethod("makeClothes");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}
总结
- JDK动态代理实际上是通过根据代理类全限定名和被代理接口,生成一个
byte[]
类型的proxyClassFile
文件,然后再通过本地方法defineClass0
加载类到JVM
中,classLoader
与被代理接口用的同一个AppClassLoader
,然后InvocationHandler
对象是作为代理类的成员域,通过构造函数参数传入
- 当代理类调用被代理接口中的方法的时候,最终调用到的是
InvocationHandler
对象的invoke
方法,方法的参数包含被代理接口的方法
- 生成代理类的参数
- classLoader:被代理类的类加载器
- interface:被代理类的顶层接口
- invocationHandler:InvocationHandler的实现类,主要实现invoke方法增强的作用