java动态代理源码解析
Posted allenli263
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java动态代理源码解析相关的知识,希望对你有一定的参考价值。
众所周知,java动态代理同反射原理一直是许多框架的底层实现,之前一直没有时间来分析动态代理的底层源码,现结合源码分析一下动态代理的底层实现
类和接口
java动态代理的主要类和接口有:java.lang.reflect.Proxy、java.lang.reflect.InvocationHandler
1 java.lang.reflect.Proxy:动态代理机制的主类,提供一组静态方法为一组接口动态的生成对象和代理类。
1、public static InvocationHandler getInvocationHandler(Object var0) -> 该方法用于获取指定代理对象所关联的调用处理器
2、public static Class<?> getProxyClass(ClassLoader var0, Class... var1) -> 该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
3、public static Object newProxyInstance(ClassLoader var0, Class<?>[] var1, InvocationHandler var2) ->方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
2 java.lang.reflect.InvocationHandler:调用处理器接口,自定义invoke方法,用于实现对于真正委托类的代理访问
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
3 java.lang.ClassLoader:类装载器类
将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy类与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中。
demo
public interface HelloService { void sayHello(); }
public class HelloServiceImpl implements HelloService{ @Override public void sayHello() { System.out.println("hello 张三"); } }
public class HelloServiceProxy implements InvocationHandler{ private Object target; public Object bind(Object target, Class[] interfaces) { 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 { Object result; System.out.println("###########这里是动态代理##########"); //反射方法前调用 System.out.println("调用前"); //反射执行方法 相当于调用target.sayHelllo; result = method.invoke(target,args); //反射方法后调用. System.out.println("调用后"); return result; } }
public class ProxyTest { public static void main(String[] args) { HelloServiceProxy proxy = new HelloServiceProxy(); HelloService service = new HelloServiceImpl(); HelloService serviceProxy = (HelloService)proxy.bind(service, new Class[] {HelloService.class}); serviceProxy.sayHello(); } }
运行结果:
源码分析:
1 Proxy类的静态方法newProxyInstance方法
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { //验证传入的InvocationHandler是否为空 Objects.requireNonNull(h); //克隆代理类实现的接口 final Class<?>[] intfs = interfaces.clone(); //获得安全管理器 final SecurityManager sm = System.getSecurityManager(); //检查创建代理类所需的权限 if (sm != null) { checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } /* * Look up or generate the designated proxy class. * 查找或者生成特定的代理类(如果缓存中存在,则直接获取) */ Class<?> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. */ try { //权限校验 if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } //获取参数类型是InvocationHandler.class的代理类构造器 final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; //如果代理类是不可访问的, 就使用特权将它的构造器设置为可访问 if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); } //传入InvocationHandler实例去构造一个代理类的实例,所有代理类都继承自Proxy,而Proxy构造方法需要InvocationHandler实例作为参数 return cons.newInstance(new Object[]{h}); } catch (IllegalAccessException|InstantiationException e) { throw new InternalError(e.toString(), e); } catch (InvocationTargetException e) { Throwable t = e.getCause(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else { throw new InternalError(t.toString(), t); } } catch (NoSuchMethodException e) { throw new InternalError(e.toString(), e); } }
从newProxyInstance方法看出,产生代理类核心代码在getProxyClass0
2 Proxy类的静态方法getProxyClass0方法
1 private static Class<?> getProxyClass0(ClassLoader loader, 2 Class<?>... interfaces) { 3 if (interfaces.length > 65535) { 4 throw new IllegalArgumentException("interface limit exceeded"); 5 } 6 7 // If the proxy class defined by the given loader implementing 8 // the given interfaces exists, this will simply return the cached copy; 9 // otherwise, it will create the proxy class via the ProxyClassFactory 10 //如果由实现给定接口的代理类存在,这将简单地返回缓存的副本;否则,将通过ProxyClassFactory创建代理类 11 return proxyClassCache.get(loader, interfaces); 12 }
getProxyClass0通过类加载器和接口集合去缓存里面获取,如果能找到代理类就直接返回,否则就会调用ProxyClassFactory这个工厂去生成一个代理类,下面我们看下Proxy的静态内部类ProxyClassFactory
3 ProxyClassFactory
1 private static final class ProxyClassFactory 2 implements BiFunction<ClassLoader, Class<?>[], Class<?>> 3 { 4 // prefix for all proxy class names 代理类名称前缀 5 private static final String proxyClassNamePrefix = "$Proxy"; 6 7 // next number to use for generation of unique proxy class names, 用原子类来生成代理类的序号, 保证序号唯一 8 private static final AtomicLong nextUniqueNumber = new AtomicLong(); 9 10 @Override 11 public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { 12 13 Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); 14 for (Class<?> intf : interfaces) { 15 /* 16 * Verify that the class loader resolves the name of this 17 * interface to the same Class object. 18 */ 19 Class<?> interfaceClass = null; 20 try { 21 interfaceClass = Class.forName(intf.getName(), false, loader); 22 } catch (ClassNotFoundException e) { 23 } 24 //intf是否可以由指定的类加载进行加载 25 if (interfaceClass != intf) { 26 throw new IllegalArgumentException( 27 intf + " is not visible from class loader"); 28 } 29 /* 30 * Verify that the Class object actually represents an 31 * interface. 32 * intf是否是一个接口 33 */ 34 if (!interfaceClass.isInterface()) { 35 throw new IllegalArgumentException( 36 interfaceClass.getName() + " is not an interface"); 37 } 38 /* 39 * Verify that this interface is not a duplicate. 40 * intf在数组中是否有重复 41 */ 42 if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { 43 throw new IllegalArgumentException( 44 "repeated interface: " + interfaceClass.getName()); 45 } 46 } 47 // package to define proxy class in 生成代理类的包名 48 String proxyPkg = null; 49 // 代理类的访问标志, 默认是public final 50 int accessFlags = Modifier.PUBLIC | Modifier.FINAL; 51 52 /* 53 * Record the package of a non-public proxy interface so that the 54 * proxy class will be defined in the same package. Verify that 55 * all non-public proxy interfaces are in the same package. 56 * 验证所有非公共代理接口都在同一个包中 57 */ 58 for (Class<?> intf : interfaces) { 59 //获取接口的访问标志 60 int flags = intf.getModifiers(); 61 //如果接口的访问标志不是public, 那么生成代理类的包名和接口包名相同 62 if (!Modifier.isPublic(flags)) { 63 //生成的代理类的访问标志设置改为final 64 accessFlags = Modifier.FINAL; 65 String name = intf.getName(); 66 int n = name.lastIndexOf(‘.‘); 67 String pkg = ((n == -1) ? "" : name.substring(0, n + 1)); 68 if (proxyPkg == null) { 69 proxyPkg = pkg; 70 } else if (!pkg.equals(proxyPkg)) { 71 //代理类如果实现不同包的接口, 并且接口都不是public的, 那么就会在这里报错 72 throw new IllegalArgumentException( 73 "non-public interfaces from different packages"); 74 } 75 } 76 } 77 78 if (proxyPkg == null) { 79 // if no non-public proxy interfaces, use com.sun.proxy package 如果没有非公共代理接口,那生成的代理类都放到默认的包下:com.sun.proxy 80 proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; 81 } 82 83 /* 84 * Choose a name for the proxy class to generate. 85 * 生成代理类的全限定名, 包名+前缀+序号, 例如:com.sun.proxy.$Proxy0 86 */ 87 long num = nextUniqueNumber.getAndIncrement(); 88 String proxyName = proxyPkg + proxyClassNamePrefix + num; 89 90 /* 91 * Generate the specified proxy class. 92 * 这里是核心, 用ProxyGenerator来生成字节码, 该类放在sun.misc包下 93 */ 94 byte[] proxyClassFile = ProxyGenerator.generateProxyClass( 95 proxyName, interfaces, accessFlags); 96 //根据二进制文件生成相应的Class实例 97 try { 98 return defineClass0(loader, proxyName, 99 proxyClassFile, 0, proxyClassFile.length); 100 } catch (ClassFormatError e) { 101 /* 102 * A ClassFormatError here means that (barring bugs in the 103 * proxy class generation code) there was some other 104 * invalid aspect of the arguments supplied to the proxy 105 * class creation (such as virtual machine limitations 106 * exceeded). 107 */ 108 throw new IllegalArgumentException(e.toString()); 109 } 110 } 111 }
ProxyClassFactory中生成代理类核心代码 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);下面我们继续分析ProxyGenerator.generateProxyClass
4 ProxyGenerator.generateProxyClass
1 public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) { 2 //构造ProxyGenerator对象 3 ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2); 4 //核心代码,生成代理类字节码文件 5 final byte[] var4 = var3.generateClassFile(); 6 //如果需要保存生成的字节码文件,则将字节码文件写入磁盘 7 if(saveGeneratedFiles) { 8 AccessController.doPrivileged(new PrivilegedAction() { 9 public Void run() { 10 try { 11 int var1 = var0.lastIndexOf(46); 12 Path var2; 13 //生成存储路径 14 if(var1 > 0) { 15 Path var3 = Paths.get(var0.substring(0, var1).replace(‘.‘, File.separatorChar), new String[0]); 16 Files.createDirectories(var3, new FileAttribute[0]); 17 var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class"); 18 } else { 19 var2 = Paths.get(var0 + ".class", new String[0]); 20 } 21 //将字节码文件写入磁盘 22 Files.write(var2, var4, new OpenOption[0]); 23 return null; 24 } catch (IOException var4x) { 25 throw new InternalError("I/O exception saving generated file: " + var4x); 26 } 27 } 28 }); 29 } 30 //返回字节码文件 31 return var4; 32 }
5 ProxyGenerator.generateClassFile
跟踪了这么久源码,大boss终于出现了,下面我们分析ProxyGenerator.generateClassFile方法
1 private byte[] generateClassFile() { 2 //1、将所有的方法组装成ProxyMethod对象 3 //首先为代理类生成toString, hashCode, equals等代理方法 4 this.addProxyMethod(hashCodeMethod, Object.class); 5 this.addProxyMethod(equalsMethod, Object.class); 6 this.addProxyMethod(toStringMethod, Object.class); 7 Class[] var1 = this.interfaces; 8 int var2 = var1.length; 9 10 int var3; 11 Class var4; 12 //遍历每一个接口的每一个方法, 并生成ProxyMethod对象 13 for(var3 = 0; var3 < var2; ++var3) { 14 var4 = var1[var3]; 15 Method[] var5 = var4.getMethods(); 16 int var6 = var5.length; 17 18 for(int var7 = 0; var7 < var6; ++var7) { 19 Method var8 = var5[var7]; 20 this.addProxyMethod(var8, var4); 21 } 22 } 23 24 Iterator var11 = this.proxyMethods.values().iterator(); 25 26 List var12; 27 while(var11.hasNext()) { 28 var12 = (List)var11.next(); 29 checkReturnTypes(var12); 30 } 31 32 //2、组装要生成的class文件的所有的字段信息和方法信息 33 Iterator var15; 34 try { 35 //添加构造器方法 36 this.methods.add(this.generateConstructor()); 37 var11 = this.proxyMethods.values().iterator(); 38 39 //遍历缓存中的代理方法 40 while(var11.hasNext()) { 41 var12 = (List)var11.next(); 42 var15 = var12.iterator(); 43 44 while(var15.hasNext()) { 45 ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next(); 46 //添加代理类的静态字段, 例如:private static Method m1; 47 this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10)); 48 //添加代理类的代理方法 49 this.methods.add(var16.generateMethod()); 50 } 51 } 52 53 //添加代理类的静态字段初始化方法 54 this.methods.add(this.generateStaticInitializer()); 55 } catch (IOException var10) { 56 throw new InternalError("unexpected I/O Exception", var10); 57 } 58 59 if(this.methods.size() > ‘uffff‘) { 60 throw new IllegalArgumentException("method limit exceeded"); 61 } else if(this.fields.size() > ‘uffff‘) { 62 throw new IllegalArgumentException("field limit exceeded"); 63 } else { 64 //3、写入最终的class文件 65 //验证常量池中存在代理类的全限定名 66 this.cp.getClass(dotToSlash(this.className)); 67 //验证常量池中存在代理类父类的全限定名 68 this.cp.getClass("java/lang/reflect/Proxy"); 69 var1 = this.interfaces; 70 var2 = var1.length; 71 72 //验证常量池存在代理类接口的全限定名 73 for(var3 = 0; var3 < var2; ++var3) { 74 var4 = var1[var3]; 75 this.cp.getClass(dotToSlash(var4.getName())); 76 } 77 78 //接下来要开始写入文件了,设置常量池只读 79 this.cp.setReadOnly(); 80 ByteArrayOutputStream var13 = new ByteArrayOutputStream(); 81 DataOutputStream var14 = new DataOutputStream(var13); 82 83 try { 84 //1.写入魔数 85 var14.writeInt(-889275714); 86 //2.写入次版本号 87 var14.writeShort(0); 88 //3.写入主版本号 89 var14.writeShort(49); 90 //4.写入常量池 91 this.cp.write(var14); 92 //5.写入访问修饰符 93 var14.writeShort(this.accessFlags); 94 //6.写入类索引 95 var14.writeShort(this.cp.getClass(dotToSlash(this.className))); 96 //7.写入父类索引, 生成的代理类都继承自Proxy 97 var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy")); 98 //8.写入接口计数值 99 var14.writeShort(this.interfaces.length); 100 101 Class[] var17 = this.interfaces; 102 int var18 = var17.length; 103 104 //9.写入接口集合 105 for(int var19 = 0; var19 < var18; ++var19) { 106 Class var22 = var17[var19]; 107 var14.writeShort(this.cp.getClass(dotToSlash(var22.getName()))); 108 } 109 //10.写入字段计数值 110 var14.writeShort(this.fields.size()); 111 var15 = this.fields.iterator(); 112 //11.写入字段集合 113 while(var15.hasNext()) { 114 ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next(); 115 var20.write(var14); 116 } 117 //12.写入方法计数值 118 var14.writeShort(this.methods.size()); 119 var15 = this.methods.iterator(); 120 //13.写入方法集合 121 while(var15.hasNext()) { 122 ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next(); 123 var21.write(var14); 124 } 125 //14.写入属性计数值, 代理类class文件没有属性所以为0 126 var14.writeShort(0); 127 //转换成二进制数组输出 128 return var13.toByteArray(); 129 } catch (IOException var9) { 130 throw new InternalError("unexpected I/O Exception", var9); 131 } 132 } 133 }
动态代理的本质:通过类加载器获取类字节码,通过类实现的接口反射获得该类的属性,方法等,并生成新的字节码文件
6 代理类字节码文件分析 $Proxy0.class
1 package com.sun.proxy; 2 3 import com.doubibi.framework.util.proxy.HelloService; 4 import java.lang.reflect.InvocationHandler; 5 import java.lang.reflect.Method; 6 import java.lang.reflect.Proxy; 7 import java.lang.reflect.UndeclaredThrowableException; 8 9 public final class $Proxy0 extends Proxy 10 implements HelloService 11 { 12 //equals方法 13 private static Method m1; 14 //HelloService 的sayHello方法 15 private static Method m3; 16 //toString方法 17 private static Method m2; 18 //hashCode方法 19 private static Method m0; 20 21 //构造方法 22 public $Proxy0(InvocationHandler paramInvocationHandler) 23 throws 24 { 25 super(paramInvocationHandler); 26 } 27 28 public final boolean equals(Object paramObject) 29 throws 30 { 31 try 32 { 33 return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue(); 34 } 35 catch (Error|RuntimeException localError) 36 { 37 throw localError; 38 } 39 catch (Throwable localThrowable) 40 { 41 throw new UndeclaredThrowableException(localThrowable); 42 } 43 } 44 45 //调用了invocationHandler的invoke方法,invoke执行了HelloService 的sayHello方法 46 public final void sayHello() 47 throws 48 { 49 try 50 { 51 this.h.invoke(this, m3, null); 52 return; 53 } 54 catch (Error|RuntimeException localError) 55 { 56 throw localError; 57 } 58 catch (Throwable localThrowable) 59 { 60 throw new UndeclaredThrowableException(localThrowable); 61 } 62 } 63 64 public final String toString() 65 throws 66 { 67 try 68 { 69 return (String)this.h.invoke(this, m2, null); 70 } 71 catch (Error|RuntimeException localError) 72 { 73 throw localError; 74 } 75 catch (Throwable localThrowable) 76 { 77 throw new UndeclaredThrowableException(localThrowable); 78 } 79 } 80 81 public final int hashCode() 82 throws 83 { 84 try 85 { 86 return ((Integer)this.h.invoke(this, m0, null)).intValue(); 87 } 88 catch (Error|RuntimeException localError) 89 { 90 throw localError; 91 } 92 catch (Throwable localThrowable) 93 { 94 throw new UndeclaredThrowableException(localThrowable); 95 } 96 } 97 98 static 99 { 100 try 101 { 102 m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") }); 103 m3 = Class.forName("com.doubibi.framework.util.proxy.HelloService").getMethod("sayHello", new Class[0]); 104 m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); 105 m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); 106 return; 107 } 108 catch (NoSuchMethodException localNoSuchMethodException) 109 { 110 throw new NoSuchMethodError(localNoSuchMethodException.getMessage()); 111 } 112 catch (ClassNotFoundException localClassNotFoundException) 113 { 114 throw new NoClassDefFoundError(localClassNotFoundException.getMessage()); 115 } 116 } 117 }
代理类$Proxy0调用了invocationHandler也就是的helloServiceProxy的invoke方法,而invoke通过反射执行了HelloService 的sayHello方法也就是HelloServiceImpl的sayHello方法。
自此java动态代理源码分析完成,笔者对动态代理理解更加深刻,如有不当之处还请各位读者指正
以上是关于java动态代理源码解析的主要内容,如果未能解决你的问题,请参考以下文章