Java实现代理的方式
继承代理
聚合代理
动态代理
- 实现自己的动态代理,生成动态代理类并且返回代理类对象,这里 目标对象只能实现一个接口
- 思路

package test.utils;
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.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ProxyUtil {
private static final String PACKAGE_NAME = "package";
private static final String IMPORT = "import";
private static final String PUBLIC = "public";
private static final String PRIVATE = "private";
private static final String CLASS = "class";
private static final String CLASS_PRE_NAME = "";
private static final String IMPLEMENTS = "implements";
private static final String TARGET_NAME = "target";
private static final String ARG_NAME_PRE = "var";
private static final String RETURN = "return";
private static final String JAVA_FILE_SUFFIX_NAME = ".java";
private static final String OBJECT = "Object";
private static final String CLASS_STORED_LOCATION = "D:\\apps\\java-develop\\alibaba-repository\\com\\xauv\\";
private static final String CLASS_PACKAGE_LOCATION = "com.xauv";
private static final String NEWLINE = "\n";
private static final String TAB = "\t";
private static final String TAB_METHOD_CONTENT = "\t\t";
private static final String SPILT_SYMBOL = ";";
private static final String SPACE = " ";
private static final String COMMA = ",";
private static final String CALCULATE_SYMBOL = ".";
private static final String CURLY_BRACES_PRE = "{";
private static final String CURLY_BRACES_AFTER = "}";
private static final String PARENTHESES_PRE = "(";
private static final String PARENTHESES_AFTER = ")";
public static Object newInstance(String proxyClassName, Object target) {
Class[] targetInterfaces = target.getClass().getInterfaces();
Class targetInterface = targetInterfaces[0];
StringBuilder stringBuilder = new StringBuilder();
appendPackageInfo(stringBuilder);
appendImportInfo(stringBuilder, targetInterfaces);
appendClassHeadInfo(stringBuilder, targetInterfaces, proxyClassName);
appendConstructorInfo(stringBuilder, proxyClassName, targetInterfaces);
appendAllDeclaredMethods(stringBuilder, targetInterfaces);
try {
File file = new File(CLASS_STORED_LOCATION +
CLASS_PRE_NAME + proxyClassName + JAVA_FILE_SUFFIX_NAME);
if(!file.exists()) {
file.createNewFile();
}
FileWriter fileWriter = new FileWriter(file);
fileWriter.write(stringBuilder.toString());
fileWriter.flush();
fileWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
Iterable units = fileMgr.getJavaFileObjects(CLASS_STORED_LOCATION + CLASS_PRE_NAME +
proxyClassName + JAVA_FILE_SUFFIX_NAME);
JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);
t.call();
fileMgr.close();
URL[] urls = new URL[]{new URL("file:D:\\apps\\java-develop\\alibaba-repository\\")};
URLClassLoader urlClassLoader = new URLClassLoader(urls);
Class clazz = urlClassLoader.loadClass(
CLASS_PACKAGE_LOCATION + "." + CLASS_PRE_NAME+proxyClassName);
Constructor constructor = clazz.getConstructor(targetInterface);
Object proxy = constructor.newInstance(target);
return proxy;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static void appendPackageInfo(StringBuilder stringBuilder) {
stringBuilder.append(PACKAGE_NAME)
.append(SPACE)
.append(CLASS_PACKAGE_LOCATION)
.append(SPILT_SYMBOL)
.append(NEWLINE);
}
private static void appendImportInfo(StringBuilder stringBuilder, Class[] interfaces) {
for (int i=0;i<interfaces.length;i++) {
stringBuilder.append(IMPORT)
.append(SPACE)
.append(interfaces[i].getName())
.append(SPILT_SYMBOL)
.append(NEWLINE);
}
}
private static void appendClassHeadInfo(StringBuilder stringBuilder, Class[] interfaces, String proxyClassName) {
stringBuilder.append(PUBLIC)
.append(SPACE)
.append(CLASS)
.append(SPACE);
String newProxyClassName = CLASS_PRE_NAME + proxyClassName;
stringBuilder.append(newProxyClassName);
stringBuilder.append(SPACE);
stringBuilder.append(IMPLEMENTS);
stringBuilder.append(SPACE);
StringBuilder implementsInterfacesContent = new StringBuilder();
for(int i=0;i<interfaces.length;i++) {
implementsInterfacesContent.append(interfaces[i].getSimpleName());
if(i<interfaces.length-1) {
implementsInterfacesContent.append(COMMA).append(SPACE);
}
}
stringBuilder.append(implementsInterfacesContent);
stringBuilder.append(CURLY_BRACES_PRE);
stringBuilder.append(NEWLINE);
}
private static void appendConstructorInfo(StringBuilder stringBuilder,
String proxyClassName, Class[] interfaces) {
stringBuilder.append(TAB);
stringBuilder.append(PRIVATE);
stringBuilder.append(SPACE);
stringBuilder.append(interfaces[0].getSimpleName());
stringBuilder.append(SPACE);
stringBuilder.append(TARGET_NAME);
stringBuilder.append(SPILT_SYMBOL);
stringBuilder.append(NEWLINE);
stringBuilder.append(TAB);
stringBuilder.append(PUBLIC);
stringBuilder.append(SPACE);
stringBuilder.append(proxyClassName);
stringBuilder.append(PARENTHESES_PRE);
stringBuilder.append(interfaces[0].getSimpleName()).
append(SPACE).append(TARGET_NAME);
stringBuilder.append(PARENTHESES_AFTER);
stringBuilder.append(SPACE);
stringBuilder.append(CURLY_BRACES_PRE);
stringBuilder.append(TAB);
stringBuilder.append(TAB);
stringBuilder.append(NEWLINE);
stringBuilder.append(TAB_METHOD_CONTENT);
stringBuilder.append("this.").append(TARGET_NAME).append("=")
.append(TARGET_NAME).append(SPILT_SYMBOL);
stringBuilder.append(NEWLINE);
stringBuilder.append(TAB_METHOD_CONTENT);
stringBuilder.append("System.out.println(\"代理对象初始化\");");
stringBuilder.append(NEWLINE);
stringBuilder.append(TAB);
stringBuilder.append(CURLY_BRACES_AFTER);
stringBuilder.append(NEWLINE);
}
private static void appendAllDeclaredMethods(StringBuilder stringBuilder,
Class[] interfaces) {
List<Method> methodList = new ArrayList<Method>();
for(int i=0;i<interfaces.length;i++) {
Method[] methods = interfaces[i].getDeclaredMethods();
methodList.addAll(Arrays.asList(methods));
}
for(int methodIndex=0;methodIndex<methodList.size();methodIndex++) {
Method method = methodList.get(methodIndex);
stringBuilder.append(TAB);
stringBuilder.append(PUBLIC);
stringBuilder.append(SPACE);
stringBuilder.append(method.getReturnType().getSimpleName());
stringBuilder.append(SPACE);
stringBuilder.append(method.getName());
stringBuilder.append(PARENTHESES_PRE);
Class<?>[] parameterTypes = method.getParameterTypes();
int index = 0;
StringBuilder argsSb = new StringBuilder();
for (int i = 0; i <parameterTypes.length ; i++) {
stringBuilder.append(parameterTypes[i].getSimpleName());
stringBuilder.append(SPACE);
stringBuilder.append(ARG_NAME_PRE).append(index);
argsSb.append(ARG_NAME_PRE).append(index);
index++;
if(i < parameterTypes.length-1) {
stringBuilder.append(COMMA);
stringBuilder.append(SPACE);
argsSb.append(COMMA).append(SPACE);
}
}
stringBuilder.append(PARENTHESES_AFTER);
stringBuilder.append(SPACE);
stringBuilder.append(CURLY_BRACES_PRE);
stringBuilder.append(NEWLINE);
stringBuilder.append(TAB);
stringBuilder.append(TAB);
stringBuilder.append("System.out.println(\"代理类中 -- 目标对象逻辑\");");
stringBuilder.append(NEWLINE);
if(!method.getReturnType().getSimpleName().equals("void")) {
stringBuilder.append(TAB_METHOD_CONTENT);
stringBuilder.append(RETURN);
stringBuilder.append(SPACE);
stringBuilder.append(TARGET_NAME).append(CALCULATE_SYMBOL).append(method.getName())
.append(PARENTHESES_PRE).append(argsSb).append(PARENTHESES_AFTER).append(SPILT_SYMBOL);
stringBuilder.append(NEWLINE);
stringBuilder.append(NEWLINE);
}
stringBuilder.append(TAB);
stringBuilder.append(CURLY_BRACES_AFTER);
stringBuilder.append(NEWLINE);
if(methodIndex < methodList.size() - 1) {
continue;
}
stringBuilder.append(CURLY_BRACES_AFTER);
}
}
}
- 用法:

JDK动态代理
- 通过反射得到字节码
- 把字节码转换成Class,这个转换方法事 native 方法,在openjdk中实现,使用 C/C++ 实现
CGLIB
性能对比(使用主要看场景)
Javassist(字节码编程)