Spring中常用到JDK动态代理和CGLIB动态代理,让他们帮我们生成对目标对象增强后的代理对象,避免了在这个工程中手动新建代理类文件导致类爆炸,手写动态代理也是以此为目标。
/**
* 目标对象
* @author l
*/
public interface TargetInterface {
/**
* 目标对象方法
* @param str1 参数
* @param str2 参数
*/
void query(String str1, String str2);
}
/**
* 目标对象的具体实现类
* @author l
*/
public class TargetImpl implements TargetInterface {
@Override
public void query(String str1, String str2) {
System.out.println("target");
}
}
import java.io.FileWriter;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
/**
* 用来生成代理类的工具
* 应该在这里将生成的.java文件编译成.class文件,未在代码中体现
* @author l
*/
public class ProxyUtil {
public static Object getInstance(Class<?> target) {
StringBuffer stringBuffer = new StringBuffer();
String line = "\r";
String tab = "\t";
stringBuffer.append("package com.depthmind.proxy.jdk;").append(line);
stringBuffer.append("public class $Proxy implements TargetInterface{").append(line);
stringBuffer.append(tab).append("TargetInterface target;").append(line);
stringBuffer.append(tab).append("public $Proxy(TargetInterface" + " target){").append(line);
stringBuffer.append(tab).append(tab).append("this.target = target;").append(line);
stringBuffer.append(tab).append("}").append(line);
// 获取目标对象的方法
Method[] declaredMethods = target.getDeclaredMethods();
for (Method method: declaredMethods) {
method.getModifiers();
method.getReturnType();
method.getName();
Parameter[] parameters = method.getParameters();
String params = "";
String args = "";
for (Parameter parameter : parameters) {
params += parameter.getType().getSimpleName() + " " +parameter.getName() + ",";
args += parameter.getName() + ",";
}
params = params.substring(0, params.lastIndexOf(",") -1);
args = args.substring(0, args.lastIndexOf(",") -1);
stringBuffer.append(tab).append("public " + method.getReturnType().getSimpleName() + " " + method.getName())
.append("(").append(params).append(") {").append(line)
.append(tab).append(tab).append("System.out.println(\"advisor\");").append(line)
.append(tab).append(tab).append("target." + method.getName() + "(" + args + ");").append(line)
.append(tab).append("}").append(line);
stringBuffer.append("}");
}
try {
FileWriter fileWriter = new FileWriter("/Users/xxx/Desktop/Proxy.java");
fileWriter.write(stringBuffer.toString());
fileWriter.flush();
fileWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public class Test {
@org.junit.jupiter.api.Test
public void test() {
//ProxyUtil.getInstance(TargetImpl.class);
TargetInterface target = new TargetImpl1();
target.query("1", "1");
try {
// 通过URLClassLoader去加载通过代理类工具生成的class文件
ClassLoader systemClassLoader = new URLClassLoader(new URL[]{new URL("file:\\\\/Users/xxx/Project/spring-framework/depthmind-core/build/classes/java/main/")});
Class<?> aClass = systemClassLoader.loadClass("com.depthmind.proxy.jdk.Proxy");
Constructor<?>[] constructors = aClass.getConstructors();
TargetInterface targetInterface = null;
for (Constructor<?> constructor : constructors) {
//应该根据参数拿到对应的构造器创建对象,这里简单写了
//if (constructor.getParameterCount() == 0) {
targetInterface = (TargetInterface) constructor.newInstance(target);
//}
}
targetInterface.query("1","2");
} catch (Exception e) {
e.printStackTrace();
}
}
}
在这里利用反射创建TargetInterface类型的对象时,曾想当然的直接调用class对象的newInstance()方法,由于在生成代理类的时候并没有生成无参构造器,所以会出现下面的异常
Caused by: java.lang.NoSuchMethodException: com.depthmind.proxy.jdk.Proxy.<init>()
至此自己的动态代理就实现了。