爲其餘對象提供一種代理以控制對這個對象對訪問。java
靜態代理:代理前,全部對行爲都是已知對。 不能擴展spring
動態代理:代理前,全部的行爲都是未知的。app
》 jdk:必須實現 interface,從interface中,獲取method,進行字節碼重組,生成新類。jvm
》 cgli:對類進行代理,Enhance 須要設置 被代理的類做爲 superClass,生成被代理類的子類。ide
public class Father { private Son person; //強依賴,不能擴展 public Father(Son person) { this.person = person; } public void findLove() { System.out.println("開始五色"); this.person.findLove(); System.out.println("結束"); } } public class Son { public void findLove() { System.out.println("找對象,大長腿"); } } public class StaticProxyTest { public static void main(String[] args) { Son son = new Son(); Father father = new Father(son); father.findLove(); } }
採用tom老師經典案例,meipothis
jdk代理spa
public interface Person { void findLove(); void job(); } public class XieMu implements Person{ @Override public void findLove() { System.out.println("gaofus"); System.out.println("身高175"); System.out.println("人好"); } @Override public void job() { System.out.println("salary 》 15k"); } } public class JDKMeipo implements InvocationHandler{ private XieMu target; public Object getInstance(XieMu target) { this.target = target; //生成新類 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println( "我是媒婆,已經拿到需求"); System.out.println( "開始五色"); method.invoke(this.target,args); return null; } } public class JDK58 implements InvocationHandler{ private Person target; public Object getInstance(Person target) { this.target = target; //生成新類 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println( "我是58,開始找工做 "); method.invoke(this.target,args); return null; } } public class JDKProxyTest { public static void main(String[] args) throws IOException { // Person instance = (Person) new JDKMeipo().getInstance(new XieMu()); // instance.findLove(); Person proxy = (Person) new JDK58().getInstance(new XieMu()); proxy.job(); byte[] bytes = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Person.class}); FileOutputStream fos = new FileOutputStream("$Proxy.class"); fos.write(bytes); fos.close(); } }
cgli 代理代理
public class Zhangsan { public void findLove() { System.out.println("人美"); } } public class CglibMeipo implements MethodInterceptor { public Object getInstance(Class clazz) { Enhancer enhancer = new Enhancer(); //設置生成新類的父類 enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { //加強 System.out.println( "我是媒婆,已經拿到需求"); System.out.println( "開始五色"); methodProxy.invokeSuper(o, objects); System.out.println("合適"); return null; } } public class CglibTest { public static void main(String[] args) { Zhangsan instance = (Zhangsan) new CglibMeipo().getInstance(new Zhangsan().getClass()); instance.findLove(); System.out.println(instance.getClass()); } }
GPClassLoader.java調試
public class GPClassLoader extends ClassLoader{ private File classPathFile; public GPClassLoader() { String classPath = GPClassLoader.class.getResource("").getPath(); this.classPathFile = new File(classPath); } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { String className = GPClassLoader.class.getPackage().getName() + "." + name; if (classPathFile != null) { File classFile = new File(classPathFile, name.replaceAll("\\.", "/") + ".class"); if (classFile.exists()) { FileInputStream fis = null; ByteArrayOutputStream out = null; try { fis = new FileInputStream(classFile); out = new ByteArrayOutputStream(); byte[] buff = new byte[1024]; int len; while ((len = fis.read(buff)) != -1) { out.write(buff, 0, len); } return defineClass(className, out.toByteArray(), 0, out.size()); } catch (Exception e) { } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } } return super.findClass(name); } }
GPProxy.javacode
public class GPProxy { public static Object newProxyInstance(GPClassLoader classLoader , Class<?>[] interfaces, GPInvocationHandler handler ) throws Exception { // 一、動態生成源代碼 String src = generateSrc(interfaces); //二、java文件 輸出到 磁盤 String filePath = GPProxy.class.getResource("").getPath(); System.out.println(filePath); File f = new File(filePath + "$Proxy0.java"); FileWriter fw = new FileWriter(f); fw.write(src); fw.flush(); //三、生成的java文件 編譯成 .class文件 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager manage = compiler.getStandardFileManager(null,null,null); Iterable iterable = manage.getJavaFileObjects(f); JavaCompiler.CompilationTask task = compiler.getTask(null,manage,null,null,null,iterable); task.call(); manage.close(); //四、編譯生成的.class文件加載到jvm中 Class proxyClass = classLoader.findClass("$Proxy0"); Constructor c = proxyClass.getConstructor(GPInvocationHandler.class); f.delete(); //五、返回字節碼重組後的新的代理對象 return c.newInstance(handler); } public static final String ln = "\r\n"; private static String generateSrc(Class<?>[] interfaces) { StringBuffer sb = new StringBuffer(); sb.append("package com.zzf.design.proxy.custom;" + ln); sb.append("import com.zzf.design.proxy.jdk.Person;" + ln); sb.append("import java.lang.reflect.Method;" + ln); sb.append("public class $Proxy0 implements " + interfaces[0].getName() + "{" + ln); sb.append("GPInvocationHandler h;" + ln); sb.append("public $Proxy0(GPInvocationHandler h) { " + ln); sb.append("this.h = h;"); sb.append("}" + ln); for (Method m : interfaces[0].getMethods()){ sb.append("public " + m.getReturnType().getName() + " " + m.getName() + "() {" + ln); sb.append("try{" + ln); sb.append("Method m = " + interfaces[0].getName() + ".class.getMethod(\"" + m.getName() + "\",new Class[]{});" + ln); sb.append("this.h.invoke(this,m,null);" + ln); sb.append("}catch(Throwable e){" + ln); sb.append("e.printStackTrace();" + ln); sb.append("}"); sb.append("}"); } sb.append("}" + ln); return sb.toString(); } }
InvocationHandler.java
public interface GPInvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable; }
藉此機會熟悉了下 ClassLoader ,一些IO流使用。受益不少。在此紀錄。
代理過程當中 主要就是 字節碼重組,生成了一個新類 $Proxy.java 。在平時的調試過程當中,是找不到該類的,運行時使用後,就立馬刪除了。
字節碼重組原理 //一、拿到被代理對象的引用,並獲取它的全部接口,反射獲取 //二、jdk proxy 類從新生成一個新的類,同時新的類要實現被代理類全部實現方法 //三、動態生成Java代碼,把新加的業務邏輯方法由必定的邏輯代碼去調用 //四、編譯新生成的java代碼 .class //五、在從新加載到 jvm中運行
spring AOP 是使用代理很好的一種實現。
==========================================
想學着用語言來進行描述,但還達不到程度,這更像是一份代碼筆記。
=========================================
咕泡學院