看完jdk动态代理源码,根据流程自己动手实现

本文介绍了一种自定义实现JDK动态代理的方法,通过反射生成代理类源文件,将其写入磁盘并编译成.class文件,再利用自定义类加载器加载到JVM中。文中详细展示了实现步骤及核心代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前天看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文件目录截图

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值