代理的接口
public interface Person {
int take();
}
需要被增强的类
import com.example.pattern.proxy.Person;
public class Boy implements Person {
@Override
public int take() {
System.out.println("-- boy --");
return 1;
}
}
自定义 InvocationHandler
用于提供被增强的方法 invoke()
SelfInvocationHandler.java
import java.lang.reflect.Method;
public interface SelfInvocationHandler {
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
自定义ClassLoader
重写findClass
SelfClassLoader.java
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URL;
public class SelfClassLoader extends ClassLoader {
URL classPathFile;
public SelfClassLoader() {
this.classPathFile = SelfClassLoader.class.getResource("");
}
@Override
public Class findClass(String name) throws ClassNotFoundException {
// 获取文件所在路径
String className = SelfClassLoader.class.getPackage().getName() + "." + name;
if (classPathFile != null) {
// 获取生成的 .class 文件
File classFile = new File(classPathFile.getPath(), "$Proxy0.class");
// 判断文件是否存在
if (classFile.exists()) {
// 读取文件
FileInputStream in = null;
ByteArrayOutputStream out = null;
try {
in = new FileInputStream(classFile);
out = new ByteArrayOutputStream();
byte[] buff = new byte[1024];
int len;
while ((len = in.read(buff)) != -1) {
out.write(buff, 0, len);
}
// 把字节码转化为Class
return defineClass(className, out.toByteArray(), 0, out.size());
} catch (Exception e) {
e.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
return super.findClass(name);
}
}
自定义增强类
import java.lang.reflect.Method;
public class SelfEnhancement implements SelfInvocationHandler {
private Object target;
public Object getInstance(Object person) throws Exception {
this.target = person;
Class<?> clazz = target.getClass();
return SelfProxy.newProxyInstance(new SelfClassLoader(), clazz.getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object obj = method.invoke(this.target, args);
after();
return obj;
}
private void before() {
System.out.println("before");
}
private void after() {
System.out.println("after");
}
}
自定义处理Proxy
import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
public class SelfProxy {
public static final String ln = "\r\n";
public static Object newProxyInstance(SelfClassLoader loader, Class<?>[] interfaces, SelfInvocationHandler h) {
try {
// 1. 动态代理生成源码
String src = generateSrc(interfaces);
// 2. Java文件输出到磁盘
String filePath = SelfProxy.class.getResource("").getPath();
File f = new File(filePath + "$Proxy0.java");
FileWriter fw = new FileWriter(f);
fw.write(src);
fw.flush();
fw.close();
// 编译Java文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
Iterable iterable = manager.getJavaFileObjects(f);
JavaCompiler.CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
task.call();
manager.close();
// 把class加载到内存
Class proxyClass = loader.findClass("$Proxy0");
Constructor c = proxyClass.getConstructor(SelfInvocationHandler.class);
return c.newInstance(h);
} catch (Exception e) {
e.printStackTrace();
}
return new Object();
}
public static String generateSrc(Class<?>[] interfaces) {
// 用代码写代码
StringBuffer sb = new StringBuffer();
sb.append("package com.example.pattern.proxy.dynamicproxy.selfproxy;" + ln);
sb.append("import com.example.pattern.proxy.Person;" + ln);
sb.append("import java.lang.reflect.*;" + ln);
sb.append("public class $Proxy0 implements " + interfaces[0].getName() + " {" + ln);
sb.append("SelfInvocationHandler h;" + ln);
sb.append("public $Proxy0(SelfInvocationHandler h) {" + ln);
sb.append("this.h = h;" + ln);
sb.append("}");
for (Method method : interfaces[0].getMethods()) {
Class<?>[] params = method.getParameterTypes();
StringBuffer paramNames = new StringBuffer();
StringBuffer paramValues = new StringBuffer();
StringBuffer paramClasses = new StringBuffer();
for (int i = 0; i < params.length; i++) {
Class clazz = params[i];
String type = clazz.getName();
String paramName = toLowerFirstCase(clazz.getSimpleName());
paramNames.append(type + " " + paramName);
paramValues.append(paramNames);
paramClasses.append(clazz.getName() + ".class");
if (i > 0 && i < params.length - 1) {
paramNames.append(",");
paramClasses.append(",");
paramValues.append(",");
}
}
sb.append("public " + method.getReturnType().getName() + " " + method.getName() + "(" + paramNames.toString() + ") {" + ln);
sb.append("try {" + ln);
sb.append("Method m = " + interfaces[0].getName() + ".class.getMethod(\"" + method.getName() + "\", new Class[]{" + paramClasses.toString() + "});" + ln);
sb.append(
(hasReturn(method.getReturnType()) ? "return " : "")
+ getCaseCode("this.h.invoke(this, m, new Object[]{" + paramValues.toString() + "})",
method.getReturnType()) + ";" + ln);
sb.append("} catch (Throwable e) {" + ln);
sb.append("e.printStackTrace();" + ln);
sb.append("}" + ln);
sb.append(getReturnEmptyCode(method.getReturnType()));
}
sb.append("}" + ln);
sb.append("}");
return sb.toString();
}
private static Map<Class, Class> mappings = new HashMap<>();
static {
mappings.put(int.class, Integer.class);
}
private static String getReturnEmptyCode(Class returnClass) {
if (mappings.containsKey(returnClass)) {
return "return 0;";
} else if (returnClass == void.class) {
return "";
} else {
return "return null;";
}
}
private static String getCaseCode(String code, Class<?> returnClass) {
if (mappings.containsKey(returnClass)) {
return "((" + mappings.get(returnClass).getName() + ")" + code + ")";
}
return code;
}
private static boolean hasReturn(Class<?> clazz) {
return clazz != void.class;
}
private static String toLowerFirstCase(String src) {
char[] chars = src.toCharArray();
chars[0] += 32;
return String.valueOf(chars);
}
}
测试代码
public class SelfProxyTest {
public static void main(String[] args) throws Exception {
Person instance = (Person) new SelfEnhancement().getInstance(new Boy());
instance.take();
}
}
生成的代理类文件
package com.example.pattern.proxy.dynamicproxy.selfproxy;
import com.example.pattern.proxy.Person;
import java.lang.reflect.*;
public class $Proxy0 implements com.example.pattern.proxy.Person {
SelfInvocationHandler h;
public $Proxy0(SelfInvocationHandler h) {
this.h = h;
}
public int take() {
try {
Method m = com.example.pattern.proxy.Person.class.getMethod("take", new Class[]{});
return ((java.lang.Integer) this.h.invoke(this, m, new Object[]{}));
} catch (Throwable e) {
e.printStackTrace();
}
return 0;
}
}