【动态代理】手写自己的动态代理

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>()

至此自己的动态代理就实现了。

猜你喜欢

转载自blog.csdn.net/hansirl/article/details/106609105