完整的是在扩展篇之动态代理,但还是单独把这部分内容拿出来了,主要自己模拟了JDK动态代理的Prxoy.newProxyInstance(),生成我们的一个代理类
我们自己来写一个JDK动态代理
public interface NbInvocationHandler {
public void invoke(Object o,Method m);
}
先看我们的测试类
public class MProxyTest {
public static void main(String[] args) throws Exception {
ITarget target = new MyTarget();
MInvocationImpl mInvocation = new MInvocationImpl(target);
ITarget o = (ITarget) MProxy.newProxyInstance(ITarget.class, mInvocation);
o.hello();
}
}
public class MProxy {
public static Object newProxyInstance(Class Interfaces,NbInvocationHandler h) throws Exception {
File file = generateJava(Interfaces,h);
compilerJava(file);
MyClassLoader classLoader = new MyClassLoader();
Class cl = classLoader.loadClass("com.yjm.proxy.$Proxy0");
Constructor<?> constructor = cl.getConstructor(NbInvocationHandler.class);
return constructor.newInstance(h);
}
public static File generateJava(Class Interfaces,NbInvocationHandler h) throws Exception {
String rt="\r\n";
String methodStr="";
for (Method method : Interfaces.getMethods()) {
methodStr += "@Override" + rt +
"public void " + method.getName() + "() {" + rt +
"try{" + rt +
"Method method = " + Interfaces.getName() + ".class.getMethod(\""
+ method.getName() + "\");" + rt +
"h.invoke(this,method);" + rt +
"}catch(Exception e){e.printStackTrace();}" + rt +
"}";
}
String source = "package com.yjm.proxy;" + rt +
"import java.lang.reflect.Method;" + rt +
"import com.yjm.proxy.NbInvocationHandler;" + rt +
"public class $Proxy0 implements " + Interfaces.getName() + "{" + rt +
"private NbInvocationHandler h;" + rt +
"public $Proxy0(NbInvocationHandler h) {" + rt +
"super();" + rt +
"this.h = h;" + rt +
"}" + rt +
methodStr + rt +
"}";
File dir = new File(MyClassLoader.sourecPath);
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(dir, "$Proxy0.java");
FileWriter writer = new FileWriter(file);
try {
writer.write(source);
} catch (IOException e) {
e.printStackTrace();
} finally {
writer.flush();
writer.close();
}
return file;
}
public static void compilerJava(File file) throws Exception {
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager javaFileManager = javaCompiler.getStandardFileManager((DiagnosticListener)null, (Locale)null, (Charset)null);
try {
Iterable it = javaFileManager.getJavaFileObjects(file);
File dir = new File(MyClassLoader.classPath);
if (!dir.exists()) {
dir.mkdirs();
}
JavaCompiler.CompilationTask task = javaCompiler.getTask((Writer)null, javaFileManager, (DiagnosticListener)null, Arrays.asList("-d", MyClassLoader.classPath), (Iterable)null, it);
task.call();
} catch (Exception e) {
e.printStackTrace();
} finally {
javaFileManager.close();
}
}
}
自定义了我们的类加载器 用于加载我们生成的.class文件
public class MyClassLoader extends ClassLoader {
public static final String classPath = System.getProperty("user.dir")+"/temp/class";
public static final String sourecPath = System.getProperty("user.dir")+"/temp/source";
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte [] data = loadByte(name);
return defineClass(name,data,0,data.length);
}
public byte[] loadByte(String name){
try {
name = name.replaceAll("\\.", "/");
FileInputStream fileInputStream = new FileInputStream(classPath+"/"+name+".class");
int len = fileInputStream.available();
byte [] data = new byte[len];
fileInputStream.read(data);
fileInputStream.close();
return data;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public class MInvocationImpl implements NbInvocationHandler{
private ITarget target;
public MInvocationImpl(ITarget target) {
this.target = target;
}
public void invoke(Object o, Method m) throws Exception {
System.out.println("执行前");
m.invoke(target);
System.out.println("执行后");
}
}
我们打断点看一下运行结果