话不多说,直接看代码。注意我们没用jdk的。
1、首先创建一个代理接口
public interface InvocationHandler {
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
2、生产代理对象
public class Proxy {
/**
* 生产代理对象
* @param clazz
* @param h
* @return
* @throws Exception
*/
public static Object newProxyInstance(Class clazz,InvocationHandler h) throws Exception{
//代理类类名
String cname = clazz.getName().substring(clazz.getName().lastIndexOf(".")+1) + "$Proxy0";
//手写代理类源码
StringBuilder source = getSource(clazz, h, cname);
//产生代理类的java文件
String filename = Thread.currentThread().getContextClassLoader().getResource("").getPath()
+ clazz.getPackage().getName().replaceAll("\\.", "/") +"/"+cname+".java";
System.out.println(filename);
//把源码写入到文件中
File file = new File(filename);
FileUtil.writeStringToFile(file, source.toString());
//编译
//拿到编译器
JavaCompiler complier = ToolProvider.getSystemJavaCompiler();
//文件管理者
StandardJavaFileManager fileMgr =
complier.getStandardFileManager(null, null, null);
//获取文件
Iterable units = fileMgr.getJavaFileObjects(filename);
//编译任务
CompilationTask t = complier.getTask(null, fileMgr, null, null, null, units);
//进行编译
t.call();
fileMgr.close();
//load 到内存
ClassLoader cl = ClassLoader.getSystemClassLoader();
Class<?> c = cl.loadClass(clazz.getPackage().getName() + "."+cname);
//获取构造函数Constructor
Constructor<?> ctr = c.getConstructor(h.getClass());
return ctr.newInstance(h);
}
/**
* 手写代理类源码
* @param clazz
* @param h
* @param cname
* @return
*/
private static StringBuilder getSource(Class clazz, InvocationHandler h, String cname) {
//调用处理接口
String handler = h.getClass().getName();
//换行符号
String line = "\r\n";
String space = " ";
//代理类源码
StringBuilder source = new StringBuilder();
//包声明
source.append("package" + space + clazz.getPackage().getName() + ";").append(line);
//获取类的名称
source.append(Modifier.toString(clazz.getModifiers()) + space + "class" + space + cname + space);
//继承接口
source.append("implements" + space);
Class[] interfaces = clazz.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
source.append(interfaces[i].getName());
if (i != interfaces.length - 1) {
source.append(",");
}
}
source.append("{").append(line);
//声明变量
source.append("private " + handler + " h;").append(line);
//构造方法
source.append("public " + cname + "(" + handler + " h){").append(line);
source.append("this.h=h;").append(line).append("}").append(line);
//实现所有方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
//获取方法返回类型
Class returnType = method.getReturnType();
//获取方法上的所有注释
Annotation[] annotations = method.getDeclaredAnnotations();
for (Annotation annotation : annotations) {
//打印注释类型
source.append("@" + annotation.annotationType().getName()).append(line);
}
//打印方法声明
source.append(Modifier.toString(method.getModifiers()) + " " + returnType.getName() + " " + method.getName() + "(");
//获取方法的所有参数
Parameter[] parameters = method.getParameters();
//参数字符串
StringBuilder args = new StringBuilder();
for (int i = 0; i < parameters.length; i++) {
//参数的类型,形参(全是arg123..)
source.append(parameters[i].getType().getName() + " " + parameters[i].getName());
args.append(parameters[i].getName());
if (i != parameters.length - 1) {
source.append(",");
args.append(",");
}
}
source.append("){").append(line);
//方法逻辑
source.append("Object obj=null; \n try {").append(line);
source.append("Class[] args = new Class[]{" + args + "};").append(line);
source.append(Method.class.getName()+" method = " + clazz.getName() + ".class.getMethod(\"" + method.getName() + "\",args);").append(line);
source.append("obj = h.invoke(this,method,args);").append(line);
source.append("} catch (Exception e) {\n" + "e.printStackTrace();\n" + "}catch (Throwable throwable) {\n" +
"throwable.printStackTrace();\n" + "}").append(line);
//方法结束
source.append("return (obj!=null)?("+returnType.getName()+")obj:null;\n}").append(line);
}
//类结束
source.append("}");
return source;
}
}
3、有一个工具类
public class FileUtil {
public static void writeStringToFile(File file, String str){
try {
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
bufferedWriter.write(str);
bufferedWriter.flush();
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4、以上就是自己编写的jdk动态代理,我们来测试下
1)提供一个业务接口
public interface Moveable {
String move();
}
2)实现这个业务
public class Car implements Moveable {
@Override
public String move() {
try {
Thread.sleep(new Random().nextInt(1000));
System.out.println("汽车行驶中....");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "success";
}
}
3)生成代理对象
public class TimeHandler implements InvocationHandler {
private Object target;
public TimeHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object object, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
long starttime = System.currentTimeMillis();
System.out.println("开始记录时间");
Object o = method.invoke(target,args);
long endtime = System.currentTimeMillis();
System.out.println("耗时:" + (endtime - starttime) + "毫秒!");
return o;
}
}
4)调用
/**
* 测试类
* 1、声明一段源码,源码动态产生动态代理
* 2、源码产生java文件,对java文件进行编译
* 3、得到编译文件 调用编译任务 生产class文件
* 4、把class文件load到内存之中,产生代理类对象返回
*/
public static void main(String[] args) throws Exception {
Car car = new Car();
InvocationHandler h = new TimeHandler(car);
//通过反射获取该类中的方法,初始化构造函数
Moveable m = (Moveable) Proxy.newProxyInstance(Car.class, h);
String s = m.move();
System.out.println(s);
}
评论区