jdk动态代理实现(源码),包括自己实现的动态代理(1)

编程入门 行业动态 更新时间:2024-10-25 10:31:40

jdk<a href=https://www.elefans.com/category/jswz/34/1771299.html style=动态代理实现(源码),包括自己实现的动态代理(1)"/>

jdk动态代理实现(源码),包括自己实现的动态代理(1)

1.首先看一下自己实现的jdk动态代理:
UserDao:

package com.sixl.dao;public interface UserDao {public void query();public void query(String p);
}

UserDaoImpl:

package com.sixl.dao;public class UserDaoImpl implements UserDao{public void query(){System.out.println("假装查询数据库");}public void query(String aa){System.out.println(aa);}
}

CoustomInvocationHandler(用于处理代理方法逻辑的接口):

package com.sixl.dao;import java.lang.reflect.Method;public interface CoustomInvocationHandler {public Object invoke(Method method);public void setParams(Object[] params);
}

TestCustomHandler(继承CoustomInvocationHandler ,具体实现逻辑)

package com.sixl.util;import com.sixl.dao.CoustomInvocationHandler;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;public class TestCustomHandler implements CoustomInvocationHandler {Object target;Object[] params;public TestCustomHandler(Object target){this.target=target;}public void setParams(Object[] params){this.params=params;}@Overridepublic Object invoke(Method method) {try {System.out.println("----------------");return  method.invoke(target,params);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}return null;}
}

ProxyUtil(生成Proxy对象的类)

package com.sixl.proxy;import com.sixl.dao.CoustomInvocationHandler;import javax.tools.JavaCompiler;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.URL;
import java.URLClassLoader;public class ProxyUtil {/***  content --->string*  .java  io* .class** .new   反射----》class* @return*/public static Object newInstance(Class targetInf, CoustomInvocationHandler h){Object proxy=null;//String handlerName = CoustomInvocationHandler.class.Method methods[] =targetInf.getDeclaredMethods();String line="\n";String tab ="\t";String infName = targetInf.getSimpleName();String content ="";String packageContent = "package com.google;"+line;String importContent = "import "+targetInf.getName()+";"+line+"import com.sixl.dao.CoustomInvocationHandler;"+line+"import java.lang.Exception;"+line+"import java.lang.reflect.Method;"+line;String clazzFirstLineContent = "public class $Proxy implements "+infName+"{"+line;String filedContent  =tab+"private CoustomInvocationHandler h;"+line;String constructorContent =tab+"public $Proxy (CoustomInvocationHandler h){" +line+tab+tab+"this.h =h;"+line+tab+"}"+line;String methodContent = "";for (Method method : methods) {String returnTypeName = method.getReturnType().getSimpleName();String methodName =method.getName();// Sting.class String.classClass args[] = method.getParameterTypes();String argsContent = "";String paramsContent="";String argsClass="";String params= "Object[] params = new Object[]{";int flag =0;for (Class arg : args) {String temp = arg.getSimpleName();//String//String p0,Sting p1,argsContent+=temp+" p"+flag+",";paramsContent+="p"+flag+",";argsClass+=","+temp+".class";params+="p"+flag;flag++;}params+="};";if (argsContent.length()>0){argsContent=argsContent.substring(0,argsContent.lastIndexOf(","));paramsContent=paramsContent.substring(0,paramsContent.lastIndexOf(",")-1);}methodContent+=tab+"public "+returnTypeName+" "+methodName+"("+argsContent+") {"+line+tab+tab+params+line+tab+tab+"h.setParams(params);"+line+tab+tab+"Method method = null;"+line+tab+tab+"try{"+line+tab+tab+tab+"method = Class.forName(\""+targetInf.getName()+"\").getDeclaredMethod(\""+methodName+"\""+argsClass+");"+line+tab+tab+"}"+line +tab+tab+"catch(Exception e){}"+line;if (returnTypeName.equals("void")){methodContent+=tab+tab+"h.invoke(method);"+line;}else {methodContent+=tab+tab+"return ("+returnTypeName+")h.invoke(method);"+line;}methodContent+=tab+"}"+line;}content=packageContent+importContent+clazzFirstLineContent+filedContent+constructorContent+methodContent+"}";File file =new File("d:\\com\\google\\$Proxy.java");try {if (!file.exists()) {file.createNewFile();}FileWriter fw = new FileWriter(file);fw.write(content);fw.flush();fw.close();//编译,只需了解这部分代码JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);Iterable units = fileMgr.getJavaFileObjects(file);JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units);t.call();fileMgr.close();URL[] urls = new URL[]{new URL("file:D:\\\\")};//使用URLClassLoader类加载器将class文件加载到内存中生成$Proxy的Class类URLClassLoader urlClassLoader = new URLClassLoader(urls);Class clazz = urlClassLoader.loadClass("com.google.$Proxy");//通过反射得到构造方法的方式得到对象并返回Constructor constructor = clazz.getConstructor(CoustomInvocationHandler.class);proxy = constructor.newInstance(h);//clazz.newInstance();//Class.forName()}catch (Exception e){e.printStackTrace();}return proxy;}
}

测试类:

package com.sixl.test;import com.sixl.dao.LubanDao;
import com.sixl.dao.LubanDaoImpl;
import com.sixl.dao.UserDao;
import com.sixl.dao.UserDaoImpl;
import com.sixl.proxy.ProxyUtil;
import com.sixl.util.LubanInvocationHandler;
import com.sixl.util.TestCustomHandler;
import sun.misc.ProxyGenerator;
public class Test {public static void main(String[] args) {UserDao proxy1= (UserDao)ProxyUtil.newInstance(UserDao.class, new TestCustomHandler(new UserDaoImpl()));proxy1.query("123");}
}

可以得到生成的代理类:

package com.google;
import com.sixl.dao.LubanDao;
import com.sixl.dao.CoustomInvocationHandler;
import java.lang.Exception;
import java.lang.reflect.Method;
public class $Proxy implements LubanDao{private CoustomInvocationHandler h;public $Proxy (CoustomInvocationHandler h){this.h =h;}public String proxy() {Object[] params = new Object[]{};h.setParams(params);Method method = null;try{method = Class.forName("com.sixl.dao.LubanDao").getDeclaredMethod("proxy");}catch(Exception e){}return (String)h.invoke(method);}
}

主要流程为:
.java---->.class---->加载到jvm中----->Object
这里自定义的CoustomInvocationHandler的invoke方法没有传params和Object,而是作为属性设置进去,可以更改为直接将params作为invoke方法的参数。
ProxyUtil主要根据接口和InvocationHandler生成代理的java文件,通过编译生成.class文件,再通过URLClassLoader加载到内存中生成代理类的Class,然后生成代理对象。
存在一定的缺陷:
1.首先要生成文件
2.需要动态编译class
3.需要一个URLClassLoader
对于性能来说,最大的影响在于对文件IO的操作。本动态代理需要生成java文件,读取java文件,因此效率会很低。

更多推荐

jdk动态代理实现(源码),包括自己实现的动态代理(1)

本文发布于:2024-03-12 22:51:03,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1732595.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:动态   源码   jdk

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!