一,JDK动态代理
在纯手写动态代理前,首先分析一套标准JDK动态代理的执行流程。
1,目标类顶层接口
public interface ProxyInterface {
public void targetMethod();
}
2,目标类
public class JDKProxyTarget implements ProxyInterface{
@Override
public void targetMethod() {
System.out.println("代理方法...");
}
}
3,代理类
public class JDKProxy {
private ProxyInterface proxyInterface;
public JDKProxy(ProxyInterface proxyInterface) {
this.proxyInterface = proxyInterface;
}
public Object instanceProxy() {
System.out.println("代理方法开始...");
ProxyInterface instance = (ProxyInterface) Proxy.newProxyInstance(
proxyInterface.getClass().getClassLoader(),
proxyInterface.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(proxyInterface, args);
System.out.println("代理方法结束...");
return null;
}
});
return instance;
}
}
4,测试类
public class JDKProxyTest {
public static void main(String[] args) throws Exception {
JDKProxy proxy = new JDKProxy(new JDKProxyTarget());
ProxyInterface proxyInterface = (ProxyInterface) proxy.instanceProxy();
System.out.println(proxyInterface.getClass());
proxyInterface.targetMethod();
}
}
5,代码解析
a,Proxy.newInstance()方法
* 第一个参数为目标类的类加载器
* 第二个参数为目标类的接口集合,JDK动态代理目标类必须实现一个接口,这是为了保证生成的代理类和目标类之前的强一致性关系
* 第三个参数为InvocationHandler接口的实现类,这里直接通过匿名内部类实现,重写了invoke方法
b,InvocationHandler接口实现类
* 实现该类必须重写invoke()方法,动态代理实现在代理类中该接口的实现类调用该方法,并在该方法中反射执行该方法完成整个动态代理流程;
* 第一个参数为生成的动态代理对象;
* 第二个参数为动态代理在客户端执行的方法;
* 第三个参数为该方法的参数列表;
* 通过反射来完成方法调用;
c,通过a步骤后,JDK会虚拟生成一个$Proxy0类,该类也实现了目标类实现的接口,从而多态返回该虚拟类对象,可以通过代码输出该类
* 代码
public class JDKProxyTest {
public static void main(String[] args) throws Exception {
JDKProxy proxy = new JDKProxy(new JDKProxyTarget());
ProxyInterface proxyInterface = (ProxyInterface) proxy.instanceProxy();
System.out.println(proxyInterface.getClass());
proxyInterface.targetMethod();
byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{ProxyInterface.class});
FileOutputStream outputStream = new FileOutputStream("E:\\$Proxy0.class");
outputStream.write(bytes);
outputStream.close();
}
}
* $Proxy0类 --- 生成为.class文件,直接通过IDEA进行反编译
public final class $Proxy0 extends Proxy implements ProxyInterface {
private static Method m1;
private static Method m2;
private static Method m3;
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})).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);
}
}
public final void targetMethod() 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)).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("com.gupao.designpattern.proxy.jdk.ProxyInterface").getMethod("targetMethod", 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());
}
}
}
d, 可以看到该虚拟类继承Proxy类并实现了目标类顶层接口,并反射获取了目标类中的所有方法的Method对象;
e, 同时,虚拟类也同时重写了目标类的所有方法,并通过下列方式进行调用
super.h.invoke(this, m3, (Object[])null);
super : 指该代理类的超类,也就是Proxy;
h : 点进源码可以看到这样一行声明
protected InvocationHandler h;
在虚拟类的构造器中,也获取了InvocationHandler的引用,所以,这里的h,指的也就是在匿名内部类定义的实现类对象;
h.invoke():就是调用匿名内部类中重写的invoke()方法,分别传递参数该对象(this),执行的方法(method),方法参数(null);
二,手写动态代理步骤分析
从上面标准的JDK动态流程可以看出,手写动态代理,需要这样几个类
1,SelfProxy类,定义newInstance()方法,进行代理对象创建
* 在该方法中首先需要输出代理类的.java文件
* 编译该.java文件生成.class文件
* 通过类加载器加载该.class文件
* 生成该.class文件的事例对象作为代理对象返回
2,SelfInvocationHandler接口,定义invoke()方法,在代理类中进行目标方法调用
* 在.java文件中,定义构造器,传递该类引用
* 通过SelfInvocationHandler实现类对象调用invoke()方法,实现代理方式的方法调用
3,SelfClassloader,自定义类加载器,继承JDK的ClassLoader类,实现自定义的加载方式
4,SelfJDKProxy,实现SelfInvocationHandler接口,重写invoke()方法,实现最终方法运行
三,手写动态代理代码实现
1,目标类顶层接口
public interface SelfProxyInterface {
public void targetMethod();
}
2,目标类
public class SelfJDKProxyTarget implements SelfProxyInterface{
@Override
public void targetMethod() {
System.out.println("代理方法...");
}
}
3,SelfClassLoader类 -- 自定义类加载器,加载.class到JVM内存中
public class SelfClassLoader extends ClassLoader{
private File classPathFile;
public SelfClassLoader() {
String classPath = SelfClassLoader.class.getResource("").getPath();
this.classPathFile = new File(classPath);
}
@Override
protected Class> findClass(String name) throws ClassNotFoundException {
String className = SelfClassLoader.class.getPackage().getName() + "." + name;
if (null != classPathFile) {
File classFile = new File(classPathFile, name + ".class");
if (classFile.exists()) {
FileInputStream in = null;
ByteArrayOutputStream out = null;
try {
in = new FileInputStream(classFile);
out = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int len;
while((len = in.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
return defineClass(className, out.toByteArray(), 0, out.size());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (null != in) {
in.close();
}
if (null != out) {
out.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
return null;
}
}
4,SelfProxy类 -- 生成虚拟代理类,创建代理对象
public class SelfProxy {
private static final String ENTER = "\r\n";
public static Object newInstance(SelfClassLoader classLoader, Class>[] interfaces, SelfInvocationHandler h) {
try {
// 动态生成源代码
String srcClass = generateSrc(interfaces);
// 输出Java文件
String filePath = SelfProxy.class.getResource("").getPath() + "$ProxyO.java";
System.out.println(filePath);
FileWriter fileWriter = new FileWriter(filePath);
fileWriter.write(srcClass);
fileWriter.flush();
fileWriter.close();
// 编译Java文件为class文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable iterable = fileManager.getJavaFileObjects(filePath);
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, null, null, iterable);
task.call();
fileManager.close();
// 加载编译生成的class文件到JVM
Class> proxyClass = classLoader.findClass("$ProxyO");
Constructor> constructor = proxyClass.getConstructor(SelfInvocationHandler.class);
// 删掉虚拟代理类
File file = new File(filePath);
file.delete();
// 返回字节码重组以后的代理对象
return constructor.newInstance(h);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String generateSrc(Class>[] interfaces) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("package com.gupao.designpattern.proxy.self;" + ENTER + ENTER);
stringBuilder.append("import com.gupao.designpattern.proxy.jdk.ProxyInterface;" + ENTER);
stringBuilder.append("import java.lang.reflect.Method;" + ENTER);
stringBuilder.append("public class $ProxyO implements " + interfaces[0].getName() + "{" + ENTER);
stringBuilder.append("SelfInvocationHandler h;" + ENTER);
stringBuilder.append("public $ProxyO(SelfInvocationHandler h) {" + ENTER);
stringBuilder.append("this.h = h;" + ENTER);
stringBuilder.append("}" + ENTER);
for (Method method : interfaces[0].getMethods()) {
stringBuilder.append("public " + method.getReturnType().getName() + " " + method.getName() + "() {" + ENTER);
stringBuilder.append("try {" + ENTER);
stringBuilder.append("Method m = " + interfaces[0].getName() + ".class.getMethod(\"" + method.getName() + "\", new Class[]{});" + ENTER);
stringBuilder.append("this.h.invoke(this, m, null);" + ENTER);
stringBuilder.append("} catch(Throwable able) {" + ENTER);
stringBuilder.append("able.getMessage();" + ENTER);
stringBuilder.append("}" + ENTER);
stringBuilder.append("}" + ENTER + ENTER);
}
stringBuilder.append("}" + ENTER);
return stringBuilder.toString();
}
}
该类代码的具体步骤在注释中已经写明;
5,查看生成的.java文件
package com.gupao.designpattern.proxy.self;
import com.gupao.designpattern.proxy.jdk.ProxyInterface;
import java.lang.reflect.Method;
public class $ProxyO implements com.gupao.designpattern.proxy.self.SelfProxyInterface {
SelfInvocationHandler h;
public $ProxyO(SelfInvocationHandler h) {
this.h = h;
}
public void targetMethod() {
try {
Method m = com.gupao.designpattern.proxy.self.SelfProxyInterface.class.getMethod("targetMethod", new Class[]{});
this.h.invoke(this, m, null);
} catch (Throwable able) {
able.getMessage();
}
}
}
6,查看生成的.class文件
package com.gupao.designpattern.proxy.self;
import java.lang.reflect.Method;
public class $ProxyO implements SelfProxyInterface {
SelfInvocationHandler h;
public $ProxyO(SelfInvocationHandler var1) {
this.h = var1;
}
public void targetMethod() {
try {
Method var1 = SelfProxyInterface.class.getMethod("targetMethod", new Class[0]);
this.h.invoke(this, var1, (Object[])null);
} catch (Throwable var2) {
var2.getMessage();
}
}
}
7,SelfInvocationHandler接口,定义invoke()方法
public interface SelfInvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args);
}
8,SelfJdkProxy,定义newInstance()方法创建代理对象,并实现InvocationHandler接口,重写invoke()方法,通过反射实现方法最终运行
public class SelfJDKProxy implements SelfInvocationHandler{
private SelfProxyInterface proxyInterface;
public SelfJDKProxy(SelfProxyInterface proxyInterface) {
this.proxyInterface = proxyInterface;
}
public Object instanceProxy() {
System.out.println("代理方法开始...");
SelfProxyInterface instance = (SelfProxyInterface) SelfProxy.newInstance(
new SelfClassLoader(),
proxyInterface.getClass().getInterfaces(), this);
return instance;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) {
try {
method.invoke(proxyInterface, args);
System.out.println("代理方法结束...");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
9,客户端执行
public class SelfTest {
public static void main(String[] args) {
SelfJDKProxy proxy = new SelfJDKProxy(new SelfJDKProxyTarget());
SelfProxyInterface proxyInterface = (SelfProxyInterface) proxy.instanceProxy();
System.out.println(proxyInterface);
proxyInterface.targetMethod();
}
}
10,总结
整个手写动态代理以说明问题为目的,整个流程中所有环境创建都是按照最简单方式在运行,旨在熟悉整个JDK动态代理的执行流程和底层实现;