一般来说最常见的动态代理是这么写的:
1,正常版本
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;
public class JDKProxy implements InvocationHandler {
private Object target; public Object getInstance(Object 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("JDProxy execute before..."); Object result = method.invoke(target,args); System.out.println("JDProxy execute after..."); return result; }} 2,改进版本
public class ProxyFactory { public static Object getProxyInstance(Object target) { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /* System.out.println(proxy); System.out.println(method); System.out.println(args);*/ System.out.println(“日志记录begin”); Object result = method.invoke(target, args); System.out.println(“日志记录end”); return result; } }); } } 首先跟一下Proxy.newProxyInstance
System.out.println(sonProxy.getClass());
class com.sun.proxy. P r o x y 0 代 理 类 的 c l a s s 为 Proxy0 代理类的class为 Proxy0代理类的class为Proxy,就是意味着 Proxy.newProxyInstance的功能就是产生一个 P r o x y , 而 Proxy,而 Proxy,而Proxy是什么呢?有一个骚操作
通过反编译工具查看class的源码
byte[] P r o x y 0 s = P r o x y G e n e r a t o r . g e n e r a t e P r o x y C l a s s ( " Proxy0s = ProxyGenerator.generateProxyClass(" Proxy0s=ProxyGenerator.generateProxyClass("Proxy0", new Class[]{Person.class}); FileOutputStream fileOutputStream = new FileOutputStream("E:// P r o x y 123. c l a s s " ) ; f i l e O u t p u t S t r e a m . w r i t e ( Proxy123.class"); fileOutputStream.write( Proxy123.class");fileOutputStream.write(Proxy0s); fileOutputStream.flush(); fileOutputStream.close(); 然后把 $Proxy123.class放到idea里面就能看到内容:
public final class $Proxy0 extends Proxy implements Person { private static Method m1; private static Method m3; private static Method m2; private static Method m0;
public $Proxy0(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final void findLove() throws { try { super.h.invoke(this, m3, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int hashCode() throws { try { return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m3 = Class.forName("com.huffman.pattern.proxy.dynamic_jdk.Person").getMethod("findLove"); m2 = Class.forName("java.lang.Object").getMethod("toString"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } }} 可以看出来 Proxy.newProxyInstance具体做的就是生成一个代理类$Proxy,代理类里面克隆了当前类所有方法,而且调用findxxx()方法时其实是调用在定义InvocationHandler.invoke()定义的方法;
所以我们的手写动态代理的思路为:
1,直接生成$proxy.java
2,把 p r o x y . j a v a 编 译 成 proxy.java编译成 proxy.java编译成proxy.class
3,用类加载器把$proxy.class生成class实例
4,把class实例返回代理对象
所以重写Proxy的newProxyInstance用代码实现为:
public static Object newProxyInstance(MyClassLoader classLoader,Class<?>[] interfaces,MyInvocationHandler myInvocationHandler) throws IllegalArgumentException, IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //1.动态生成java文件源码 String src=generateSrc(interfaces); //2.将java源码生成本地文件 String classPath = MyProxy.class.getResource("").getPath(); File file = new File(classPath + “ P r o x y 0. j a v a " ) ; F i l e W r i t e r f i l e W r i t e r = n e w F i l e W r i t e r ( f i l e ) ; f i l e W r i t e r . w r i t e ( s r c ) ; f i l e W r i t e r . f l u s h ( ) ; f i l e W r i t e r . c l o s e ( ) ; / / 3. 动 态 编 译 j a v a 源 码 , 生 成 c l a s s 文 件 J a v a C o m p i l e r c o m p i l e r = T o o l P r o v i d e r . g e t S y s t e m J a v a C o m p i l e r ( ) ; S t a n d a r d J a v a F i l e M a n a g e r m a n a g e = c o m p i l e r . g e t S t a n d a r d F i l e M a n a g e r ( n u l l , n u l l , n u l l ) ; I t e r a b l e i t e r a b l e = m a n a g e . g e t J a v a F i l e O b j e c t s ( f i l e ) ; J a v a C o m p i l e r . C o m p i l a t i o n T a s k t a s k = c o m p i l e r . g e t T a s k ( n u l l , m a n a g e , n u l l , n u l l , n u l l , i t e r a b l e ) ; t a s k . c a l l ( ) ; m a n a g e . c l o s e ( ) ; / / 4. 加 载 c l a s s 文 件 生 成 C l a s s 实 例 C l a s s p r o x y C l a s s = c l a s s L o a d e r . f i n d C l a s s ( " Proxy0.java"); FileWriter fileWriter = new FileWriter(file); fileWriter.write(src); fileWriter.flush(); fileWriter.close(); //3.动态编译java源码,生成class文件 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager manage = compiler.getStandardFileManager(null,null,null); Iterable iterable = manage.getJavaFileObjects(file); JavaCompiler.CompilationTask task = compiler.getTask(null,manage,null,null,null,iterable); task.call(); manage.close(); //4.加载class文件生成Class实例 Class proxyClass = classLoader.findClass(" Proxy0.java");FileWriterfileWriter=newFileWriter(file);fileWriter.write(src);fileWriter.flush();fileWriter.close();//3.动态编译java源码,生成class文件JavaCompilercompiler=ToolProvider.getSystemJavaCompiler();StandardJavaFileManagermanage=compiler.getStandardFileManager(null,null,null);Iterableiterable=manage.getJavaFileObjects(file);JavaCompiler.CompilationTasktask=compiler.getTask(null,manage,null,null,null,iterable);task.call();manage.close();//4.加载class文件生成Class实例ClassproxyClass=classLoader.findClass("Proxy0”); Constructor c = proxyClass.getConstructor(MyInvocationHandler.class);
// file.delete(); //5.根据类型Class生成代理对象 return c.newInstance(myInvocationHandler); }自定义类加载器就是把本地生成的$Proxy0.class加载到jvm
public class MyClassLoader extends ClassLoader { private File classPathFile;
public MyClassLoader(){ String classPath = MyClassLoader.class.getResource("").getPath(); this.classPathFile = new File(classPath); } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { String className = MyClassLoader.class.getPackage().getName() + "." + name; if(classPathFile != null){ File classFile = new File(classPathFile,name.replaceAll("\\.","/") + ".class"); if(classFile.exists()){ FileInputStream in = null; ByteArrayOutputStream out = null; try{ in = new FileInputStream(classFile); out = new ByteArrayOutputStream(); byte [] buff = new byte[1024]; int len; while ((len = in.read(buff)) != -1){ out.write(buff,0,len); } return defineClass(className,out.toByteArray(),0,out.size()); }catch (Exception e){ e.printStackTrace(); }finally { if(null != in){ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if(out != null){ try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } } return null; }} 至此,手动实现动态代理就完成了;