看完jdk動態代理源碼,根據流程自己動手實現

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

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章