动态代理源码分析,实现自己的动态代理
什么是代理
增強(qiáng)一個(gè)對(duì)象的功能
買(mǎi)火車(chē)票,app就是一個(gè)代理,他代理了火車(chē)站,小區(qū)當(dāng)中的代售窗口
java當(dāng)中如何實(shí)現(xiàn)代理
java實(shí)現(xiàn)的代理的兩種辦法
代理的名詞
代理對(duì)象 增強(qiáng)后的對(duì)象
目標(biāo)對(duì)象 被增強(qiáng)的對(duì)象
他們不是絕對(duì)的,會(huì)根據(jù)情況發(fā)生變化
靜態(tài)代理
繼承
代理對(duì)象繼承目標(biāo)對(duì)象,重寫(xiě)需要增強(qiáng)的方法;
缺點(diǎn):會(huì)代理類(lèi)過(guò)多,非常復(fù)雜
聚合
目標(biāo)對(duì)象和代理對(duì)象實(shí)現(xiàn)同一個(gè)接口,代理對(duì)象當(dāng)中要包含目標(biāo)對(duì)象。
缺點(diǎn):也會(huì)產(chǎn)生類(lèi)爆炸,只不過(guò)比繼承少一點(diǎn)點(diǎn)
總結(jié):如果在不確定的情況下,盡量不要去使用靜態(tài)代理。因?yàn)橐坏┠銓?xiě)代碼,就會(huì)產(chǎn)生類(lèi),一旦產(chǎn)生類(lèi)就爆炸。
動(dòng)態(tài)代理
自己模擬的動(dòng)態(tài)代理
不需要手動(dòng)創(chuàng)建類(lèi)文件(因?yàn)橐坏┦謩?dòng)創(chuàng)建類(lèi)文件,就會(huì)產(chǎn)生類(lèi)爆炸),通過(guò)接口反射生成一個(gè)類(lèi)文件,然后調(diào)用第三方的編譯技術(shù),動(dòng)態(tài)編譯這個(gè)產(chǎn)生的類(lèi)文件成class文件,繼而利用UrlclassLoader(因?yàn)檫@個(gè)動(dòng)態(tài)產(chǎn)生的class不在工程當(dāng)中所以需要使用UrlclassLoader)把這個(gè)動(dòng)態(tài)編譯的類(lèi)加載到j(luò)vm當(dāng)中,最后通過(guò)反射把這個(gè)類(lèi)實(shí)例化。
缺點(diǎn):首先要生成文件
缺點(diǎn):動(dòng)態(tài)編譯文件 class
缺點(diǎn):需要一個(gè)URLclassloader
軟件性能的最終體現(xiàn)在IO操作
package com.leon.proxy;import com.leon.dao.CoustomInvocationHandler; import com.sun.jndi.toolkit.url.UrlUtil;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.net.URL; import java.net.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.leon.dao.CoustomInvocationHandler;"+line+"import java.lang.Exception;"+"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="";int flag =0;for (Class arg : args) {String temp = arg.getSimpleName();//String//String p0,Sting p1,argsContent+=temp+" p"+flag+",";paramsContent+="p"+flag+",";flag++;}if (argsContent.length()>0){argsContent=argsContent.substring(0,argsContent.lastIndexOf(",")-1);paramsContent=paramsContent.substring(0,paramsContent.lastIndexOf(",")-1);}methodContent+=tab+"public "+returnTypeName+" "+methodName+"("+argsContent+")throws Exception {"+line+tab+tab+"Method method = Class.forName(\""+targetInf.getName()+"\").getDeclaredMethod(\""+methodName+"\");"+line+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 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();}/*** public UserDaoLog(UserDao target){* this.target =target;** }*/return proxy;} }JDK動(dòng)態(tài)代理
通過(guò)接口反射得到字節(jié)碼,然后把字節(jié)碼轉(zhuǎn)成class native openJDK c++
?
總結(jié)
以上是生活随笔為你收集整理的动态代理源码分析,实现自己的动态代理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: AOP各种表达式,aspectj的关系
- 下一篇: spring FactoryBean的知