介绍 Spring动态代理可以选择使用jdk动态代理, 或者cglib动态代理, jdk动态代理位于 java.lang.reflect 包下.
使用时涉及 接口: java.lang.reflect.InvocationHandler 动态代理类: java.lang.reflect.Proxy
注意: JDK 动态代理是基于接口的代理, 只能对实现接口的类生成代理, 不能对类进行代理
使用步骤 1.创建InvocationHandler接口的实现类, 并编写invoke方法的实现 2.创建被代理类的接口及实现类 3.使用动态代理类Proxy的静态方法生成代理类实例 4.使用实例调用方法
代码演示 按照步骤编写简易逻辑代码.
创建InvocationHandler接口的实现类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class MyInvocationHandler implements InvocationHandler { private Object target; public MyInvocationHandler (Object target) { this .target = target; } @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { System.out.println("jdk 动态代理 before . . . " ); System.out.println("当前代理方法为:" + method); Object invoke = method.invoke(target, args); System.out.println("jdk 动态代理 after . . . " ); return invoke; } }
创建被代理类的接口及实现类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public interface Subject { String getName () ; String getAge (String name) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public class SubjectImpl implements Subject { @Override public String getName () { System.out.println("SubjectImpl的获取名字方法 . . ." ); return "liuzhihang" ; } @Override public String getAge (String name) { System.out.println(name + "开始获取年龄 . . ." ); return "25" ; } }
使用动态代理类Proxy的静态方法生成代理类实例 获取代理类实例有以下两种方式, 一种是通过Proxy.newProxyInstance(..)获取, 一种是通过 Proxy.getProxyClass(..) 方式获取 1.Proxy.newProxyInstance(..)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class ProxyMainTest { public static void main (String[] args) { Subject subject = new SubjectImpl (); ClassLoader classLoader = subject.getClass().getClassLoader(); Class<?>[] interfaces = subject.getClass().getInterfaces(); MyInvocationHandler handler = new MyInvocationHandler (subject); Subject proxyInstance = (Subject) Proxy.newProxyInstance(classLoader, interfaces, handler); String name = proxyInstance.getName(); String instanceAge = proxyInstance.getAge("liuzhihang" ); System.err.println(name + " " + instanceAge); } }
2.Proxy.getProxyClass(..)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 public class ProxyMainTest { public static void main (String[] args) { try { Subject subject = new SubjectImpl (); ClassLoader classLoader = subject.getClass().getClassLoader(); Class<?>[] interfaces = subject.getClass().getInterfaces(); MyInvocationHandler handler = new MyInvocationHandler (subject); Class<?> proxyClass = Proxy.getProxyClass(classLoader, interfaces); Constructor<?> constructor = proxyClass.getConstructor(InvocationHandler.class); Subject subject1 = (Subject) constructor.newInstance(handler); String name1 = subject1.getName(); String instanceAge1 = subject1.getAge("liuzhihang" ); System.err.println(name1 + " " + instanceAge1); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) { e.printStackTrace(); } } }
执行结果 1 2 3 4 5 6 7 8 9 10 11 12 D:\jdk1.8\bin\java.exe . . . liuzhihang 25 jdk 动态代理 before . . . 当前代理方法为:public abstract java.lang.String com.liuzhihang.tool.proxy.jdk.Subject.getName() SubjectImpl的获取名字方法 . . . jdk 动态代理 after . . . jdk 动态代理 before . . . 当前代理方法为:public abstract java.lang.String com.liuzhihang.tool.proxy.jdk.Subject.getAge(java.lang.String) liuzhihang开始获取年龄 . . . jdk 动态代理 after . . . Process finished with exit code 0
结论: 代理实例在每次调用方法是都会通过代理类进行调用
相关源码解析 完整注释可自己查看相关源码, 源码过程应当DeBug多走走. 1.调用 Proxy.newProxyInstance 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 /** * 返回指定接口的代理类实例,该接口将方法调用分派给指定的调用处理程序 */ @CallerSensitive public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { // 非空校验 Objects.requireNonNull(h); final Class<?>[] intfs = interfaces.clone(); // 获取系统安全接口 final SecurityManager sm = System.getSecurityManager(); if (sm != null) { // 校验权限 checkProxyAccess(Reflection.getCallerClass(), loader, intfs); } /* * 从缓存中获取代理类 或者 生成新的代理类 */ Class<?> cl = getProxyClass0(loader, intfs); /* * 通过反射获取构造函数对象并生成代理类实例 */ try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } // 获取构造 final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; // 验证代理类的修饰符 if (!Modifier.isPublic(cl.getModifiers())) { // 修改访问权限 AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { // 将此对象的可访问标志设置为指定的布尔值, true表示反射对象在使用时应禁止Java语言访问检查, false表示反射对象应强制执行Java语言访问检查 cons.setAccessible(true); return null; } }); } //生成实例, 并将参数传入构造 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); } }
可以看出获取代理类是在 Class<?> cl = getProxyClass0(loader, intfs); 处, 继续相关逻辑 2.获取代理类相关逻辑
1 2 3 4 5 6 7 8 9 10 11 12 /** * 生成代理类, 之前必须进行权限检查 */ private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } //如果由实现给定接口的给定加载器定义的代理类存在,则它将简单地返回缓存副本; 否则,它将通过Proxy Class Factory创建代理类 return proxyClassCache.get(loader, interfaces); }
3.proxyClassCache.get(loader, interfaces); java.lang.reflect.WeakCache#get(..) 介绍
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 /** * 通过缓存查找值, 如果缓存中没有给定的(key,sub Key)对的条目或条目已被清除,则它总是评估{Key sub Key Factory}函数并可选择评估{Factory value}函数 */ public V get(K key, P parameter) { // 非空校验 Objects.requireNonNull(parameter); // 判断移除队列 expungeStaleEntries(); // 缓存key Object cacheKey = CacheKey.valueOf(key, refQueue); // 延迟加载使用二级map ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey); if (valuesMap == null) { ConcurrentMap<Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey, valuesMap = new ConcurrentHashMap<>()); if (oldValuesMap != null) { valuesMap = oldValuesMap; } } // 创建子key 并根据key 检索supplier Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); // 根据key获取supplier Supplier<V> supplier = valuesMap.get(subKey); Factory factory = null; while (true) { if (supplier != null) { // supplier 可能为 Factory 或者 CacheValue<V> 的实例, 从缓存中获取到则直接返回 V value = supplier.get(); if (value != null) { return value; } } // factory不存在则创建 if (factory == null) { factory = new Factory(key, parameter, subKey, valuesMap); } // supplier 为null if (supplier == null) { // 从valuesMap获取supplier supplier = valuesMap.putIfAbsent(subKey, factory); if (supplier == null) { // successfully installed Factory supplier = factory; } // else retry with winning supplier } else { if (valuesMap.replace(subKey, supplier, factory)) { // successfully replaced // cleared CacheEntry / unsuccessful Factory // with our Factory supplier = factory; } else { // retry with current supplier supplier = valuesMap.get(subKey); } } } }
可以发现重点在 Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); 获取 subKey 的过程中. 4.subKeyFactory.apply(key, parameter) Debug发现在此处调用的是 java.lang.reflect.Proxy.ProxyClassFactory 静态内部类, 此处根据接口的数量生成二级缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 private static final class ProxyClassFactory implements BiFunction <ClassLoader, Class<?>[], Class<?>> { private static final String proxyClassNamePrefix = "$Proxy" ; private static final AtomicLong nextUniqueNumber = new AtomicLong (); @Override public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap <>(interfaces.length); for (Class<?> intf : interfaces) { Class<?> interfaceClass = null ; try { interfaceClass = Class.forName(intf.getName(), false , loader); } catch (ClassNotFoundException e) { } if (interfaceClass != intf) { throw new IllegalArgumentException ( intf + " is not visible from class loader" ); } if (!interfaceClass.isInterface()) { throw new IllegalArgumentException ( interfaceClass.getName() + " is not an interface" ); } if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null ) { throw new IllegalArgumentException ( "repeated interface: " + interfaceClass.getName()); } } String proxyPkg = null ; int accessFlags = Modifier.PUBLIC | Modifier.FINAL; for (Class<?> intf : interfaces) { int flags = intf.getModifiers(); if (!Modifier.isPublic(flags)) { accessFlags = Modifier.FINAL; String name = intf.getName(); int n = name.lastIndexOf('.' ); String pkg = ((n == -1 ) ? "" : name.substring(0 , n + 1 )); if (proxyPkg == null ) { proxyPkg = pkg; } else if (!pkg.equals(proxyPkg)) { throw new IllegalArgumentException ( "non-public interfaces from different packages" ); } } } if (proxyPkg == null ) { proxyPkg = ReflectUtil.PROXY_PACKAGE + "." ; } long num = nextUniqueNumber.getAndIncrement(); String proxyName = proxyPkg + proxyClassNamePrefix + num; byte [] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags); try { return defineClass0(loader, proxyName, proxyClassFile, 0 , proxyClassFile.length); } catch (ClassFormatError e) { throw new IllegalArgumentException (e.toString()); } } }
5.生辰给代理类 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags); 可以在测试类中添加以下内容打印出代理类:
1 System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
代理类内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 package com.sun.proxy;import com.liuzhihang.tool.proxy.jdk.Subject;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;public final class $Proxy0 extends Proxy implements Subject { private static Method m1; private static Method m3; private static Method m2; private static Method m4; 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 String getName () throws { try { return (String)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 String getAge (String var1) throws { try { return (String)super .h.invoke(this , m4, new Object []{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException (var4); } } 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.liuzhihang.tool.proxy.jdk.Subject" ).getMethod("getName" ); m2 = Class.forName("java.lang.Object" ).getMethod("toString" ); m4 = Class.forName("com.liuzhihang.tool.proxy.jdk.Subject" ).getMethod("getAge" , Class.forName("java.lang.String" )); m0 = Class.forName("java.lang.Object" ).getMethod("hashCode" ); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError (var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError (var3.getMessage()); } } }
可以看出生成的$Proxy0类继承Proxy动态代理类并实现了Subject被代理接口, 实现所有方法 通过 super.h.invoke(this, m1, new Object[]{var1}) 内部调用了 InvocationHandler.invoke(…)方法, 通过反射调用代理实例的方法