前天看jdk动态代理,总觉得有点不爽很多代码,没看到,于是去看了代码,根据我的理解写了自己的一套动态代理实现,还可以
代理类 ZwProxy实现流程如下
1.使用反射,生成代理类的源文件
2.将源文件写入磁盘相应的文件夹中,生在.java文件
3.编译.java文件生成.class文件
4.将.class文件动态加载到jvm中(此步在自己写的类加载器中完成)
5.返回代理对象
主要是import java.lang.reflect.Proxy中功能的实现 ,还重写了类加载器findClass() ,目的是将Class类对象动态加载到jvm中
jdk只支持带接口类的代理,本套方法也是如此
接口
package cn.zw.learn.proxy.custom;
public interface Person {
public void findLove()throws Throwable;
public String getSex() throws Throwable ;
public String getName() throws Throwable;
}
被代理类
package cn.zw.learn.proxy.custom;
public class Zw implements Person {
public void findLove() {
System.out.println("我的名字叫zhaowei");
}
public String getSex() {
// TODO Auto-generated method stub
return "male";
}
public String getName() {
// TODO Auto-generated method stub
return null;
}
}
以下是我的代码
定义的InvocationHandler接口
跟原来的一样,就一句话
ZWInvocationHandler
package cn.zw.learn.proxy.custom;
import java.lang.reflect.Method;
public interface ZWInvocationHandler {
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable;
}
ZwProxy
package cn.zw.learn.proxy.custom;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class ZwProxy {
private final static String ln = "\r\n";
public static Object newProxyInstance(ZwClassLoader loader,
Class<?>[] interfaces, ZWInvocationHandler h) throws IOException,
ClassNotFoundException, NoSuchMethodException, SecurityException,
InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
// 生成源代码
String src = generateSrc(interfaces[0]);
// 将生成的源代码输出到磁盘,生成.java文件
String filePath = ZwProxy.class.getResource("").getPath();
File file = new File(filePath + "$Proxy0.java");
FileWriter fileWriter = new FileWriter(file);
fileWriter.write(src);
fileWriter.flush();
fileWriter.close();
// 编译.java文件
JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = javaCompiler.getStandardFileManager(
null, null, null);
Iterable iterable = manager.getJavaFileObjects(file);
CompilationTask task = javaCompiler.getTask(null, manager, null, null,
null, iterable);
task.call();
manager.close();
// 将.class文件动态加载到jvm中
// 返回被代理对象
Class clazz = loader.findClass("$Proxy0");
Constructor constructor = clazz
.getConstructor(ZWInvocationHandler.class);
return constructor.newInstance(h);
}
private static String generateSrc(Class<?> interfaces) {
StringBuffer buffer = new StringBuffer();
buffer.append("package cn.zw.learn.proxy.custom;" + ln);
buffer.append("import java.lang.reflect.Method;" + ln);
buffer.append("public final class $Proxy0 extends ZwProxy implements "
+ interfaces.getName() + "{" + ln);
buffer.append("ZWInvocationHandler h;" + ln);
buffer.append("public $Proxy0(ZWInvocationHandler h){ " + ln);
buffer.append("this.h=h;" + ln);
buffer.append("}" + ln);
for (Method m : interfaces.getMethods()) {
String type = m.getReturnType().getName();
buffer.append("public " + type + " " + m.getName()
+ "() throws Throwable { " + ln);
buffer.append("Method m=" + interfaces.getName()
+ ".class.getMethod(\"" + m.getName()
+ "\", new Class[]{});" + ln);
if (type.equalsIgnoreCase("void")) {
buffer.append("this.h.invoke(this,m,null);" + ln);
} else {
buffer.append("return ("
+ m.getReturnType().toString().replace("class", "")
+ ")this.h.invoke(this,m,null);" + ln);
}
buffer.append("}" + ln);
}
buffer.append("}");
return buffer.toString();
}
}
继承类加载器,并实现findClass方法
package cn.zw.learn.proxy.custom;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class ZwClassLoader extends ClassLoader {
private File baseFile;
public ZwClassLoader() {
String path = ZwClassLoader.class.getResource("").getPath();
System.out.println(path);
this.baseFile = new File(path);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
// TODO Auto-generated method stub
String className = ZwClassLoader.class.getPackage().getName() + "."
+ name;
if (baseFile != null) {
File file = new File(baseFile, name + ".class");
FileInputStream inputStream = null;
ByteArrayOutputStream bos = null;
try {
inputStream = new FileInputStream(file);
int len;
byte[] b = new byte[1024];
bos = new ByteArrayOutputStream();
while ((len = inputStream.read(b)) != -1) {
bos.write(b, 0, len);
}
return defineClass(className, bos.toByteArray(), 0, bos.size());
} catch (Exception e) {
// TODO: handle exception
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
return null;
}
测试
代理工具类
package cn.zw.learn.proxy.custom;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ZwMeiPo implements ZWInvocationHandler {
private Person target;
public Object getInstance(Person target) throws ClassNotFoundException, IOException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
this.target=target;
return ZwProxy.newProxyInstance(new ZwClassLoader(), target.getClass().getInterfaces(),this );
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("你的性别为:"+this.target.getSex());
method.invoke(target, args);
System.out.println("相亲结束");
return null;
}
}
test测试与结果
public void test1() throws Throwable{
Person person=(Person)new ZwMeiPo().getInstance(new Zw() );
person.findLove();
}
结果
你的性别为:male
我的名字叫zhaowei
相亲结束
Class文件目录截图