前天看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文件目錄截圖