谈谈对spring动态代理的理解?
1 个回答
谎言不会伤人,真相才是快刀。华仔**大概流程** 1、为接口创建代理类的字节码文件 2、使用ClassLoader将字节码文件加载到JVM 3、创建代理类实例对象,执行对象的目标方法 首先Proxy类调用newProxyInstance方法: ```java //调用动态代理实例 IUserDao userDao = (IUserDao) Proxy.newProxyInstance(classLoader, interfaces, invocationHandlerImpl); ``` newProxyInstance方法调用getProxyClass0方法生成代理类的字节码文件,getProxyClass0的源码如下: ```java /** * Generate a proxy class. */ private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } // 如果缓存中已经存在相应接口的代理类,直接返回;否则,使用ProxyClassFactory创建代理类 return proxyClassCache.get(loader, interfaces); } ``` proxyClassCache是Proxy.class的成员变量,这个变量初始化的时候会实例化出ProxyClassFactory: ```java /** * 代理类会缓存到proxyClassCache中 */ private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory()); ` ``` ProxyClassFactory中的ProxyGenerator.generateProxyClass真正生成代理类的字节码文件的地方 ```java byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); ``` ProxyGenerator.generateProxyClass()源码如下: ```java public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) { ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2); final byte[] var4 = var3.generateClassFile(); // 是否要将生成代理类的字节码文件保存到磁盘中 if (saveGeneratedFiles) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { try { int var1 = var0.lastIndexOf(46); Path var2; if (var1 > 0) { Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar)); Files.createDirectories(var3); var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class"); } else { var2 = Paths.get(var0 + ".class"); } Files.write(var2, var4, new OpenOption[0]); return null; } catch (IOException var4x) { throw new InternalError("I/O exception saving generated file: " + var4x); } } }); } return var4; } ```发布于 2021-06-28 17:18 •IP属地 浙江举报评论收藏
公众号进入网站体验更佳

