文章目录
前言
概述
什么是代理
静态代理
动态代理
正文
入口
方法1:newProxyInstance
方法2:getProxyClass0
方法3:get 获取代理
方法4:apply 创建代理
方法5:generateProxyClass
方法6:generateClassFile
代理类
总结
前言
动态代理在开发可能使用的频率不是特别高,但在一些框架里面总能看到它的身影,例如Spring AOP就是使用JDK动态代理和CGLIB动态代理两种方法,本篇文章讲解JDK动态代理原理,看它是如何对类进行增强的。
概述
什么是代理
代理就是由直接调用转为间接调用,比如我们调用出单服务A,我需要在每次调用A时都记录日志,我们可以创建一个新的类及其方法B,在B中调用A,并且插入日志,这样由原先的调用A变成B,我们可以在B做一些增强操作如日志等。B就是代理类,而A就是原生类(被代理类)。
静态代理
静态代理的静态指的是代码运行前我们就编写了代理类,并且编译生成了.class文件,程序可以读取到内存并运行这些文件,如:
接口:
public interface Person { public String work(); public String sleep(); }
代理类:
public class ProxyPerson implements Person { private Person person; public ProxyPerson(Person person) { this.person = person; } @Override public String work() { System.out.println("增强"); return person.work(); } @Override public String sleep() { System.out.println("增强"); return person.sleep(); } }
通过代理类,我们可以创建Person接口实现类,传到ProxyPerson 完成代理。
动态代理
通过上述案例,可以看到静态代理的缺点,每增加一个不同的接口,都需要编写一个代理类,当业务代理多起来之后,难以维护。而动态代理就解决了这个问题,代理类是在运行过程中产生的,不需要给每一个被代理类创建代理对象,以JDK动态代理为例:
拦截处理器:
public class ProxyHandler implements InvocationHandler { private Object target; public Object getProxy(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("增强前"); Object invoke = method.invoke(target, args); System.out.println("增强后"); return invoke; } }
接口:
public interface Person { public String work(); public String sleep(); }
实现类:
public class Teacher implements Person { @Override public String work() { String work="工作中"; System.out.println(work); return work; } @Override public String sleep() { String sleep="睡觉中"; System.out.println(sleep); return sleep; } }
测试用例:
public static void main(String[] args) { Teacher teacher=new Teacher(); ProxyHandler proxyHandle=new ProxyHandler(); Person proxy = (Person) proxyHandle.getProxy(teacher); proxy.sleep(); }
通过以上案例,可以知道我们并没有写死接口类型,无论是什么接口类型都传入原生类进行代理增强;
正文
既然我们知道动态代理概念,及其JDK动态代理的使用了,后面就来看看它的实现原理。
入口
以上述测试用例为入口,看一下Proxy.newProxyInstance是如何生成代理对象的;
public class ProxyHandler implements InvocationHandler { private Object target; public Object getProxy(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("增强前"); Object invoke = method.invoke(target, args); System.out.println("增强后"); return invoke; } }
Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this),见方法1详解
方法1:newProxyInstance
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); } /* * Look up or generate the designated proxy class. */ //生成代理Class对象 Class<?> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. */ 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() { //设置权限 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); } }
getProxyClass0(loader, intfs),见方法2详解
方法2:getProxyClass0
private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { //检验接口数量 if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } // If the proxy class defined by the given loader implementing // the given interfaces exists, this will simply return the cached copy; // otherwise, it will create the proxy class via the ProxyClassFactory //获取代理Clas对象 return proxyClassCache.get(loader, interfaces); }
public V get(K key, P parameter) { //校验校验不为空 Objects.requireNonNull(parameter); expungeStaleEntries(); //将类加载器与ReferenceQueue队列封装成CacheKey作为缓存Key Object cacheKey = CacheKey.valueOf(key, refQueue); // lazily install the 2nd level valuesMap for the particular cacheKey //尝试从缓存中获取之前处理过的缓存信息 ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey); if (valuesMap == null) { //如果不存在,则创建一个空容器并放到Map中 ConcurrentMap<Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey, valuesMap = new ConcurrentHashMap<>()); if (oldValuesMap != null) { valuesMap = oldValuesMap; } } // create subKey and retrieve the possible Supplier<V> stored by that // subKey from valuesMap //根据策略选出接口并封装Key Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); //获取当前函数式接口 Supplier<V> supplier = valuesMap.get(subKey); Factory factory = null; while (true) { if (supplier != null) { // supplier might be a Factory or a CacheValue<V> instance //获取缓存后的factory,调用get方法创建代理对象 V value = supplier.get(); if (value != null) { return value; } } // else no supplier in cache // or a supplier that returned null (could be a cleared CacheValue // or a Factory that wasn't successful in installing the CacheValue) // lazily construct a Factory //创建Factory工厂 if (factory == null) { factory = new Factory(key, parameter, subKey, valuesMap); } if (supplier == null) { //将Factory存入valuesMap中 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); } } } }
上面代码主要是为了加入缓存,创建代理逻辑在于调用Factory的get方法。
V value = supplier.get(),见方法3详解
方法3:get 获取代理
public synchronized V get() { // serialize access // re-check //校验 Supplier<V> supplier = valuesMap.get(subKey); if (supplier != this) { // something changed while we were waiting: // might be that we were replaced by a CacheValue // or were removed because of failure -> // return null to signal WeakCache.get() to retry // the loop return null; } // else still us (supplier == this) // create new value V value = null; try { //创建代理对象入口 value = Objects.requireNonNull(valueFactory.apply(key, parameter)); } finally { //没有创建成果,则移除缓存 if (value == null) { // remove us on failure valuesMap.remove(subKey, this); } } // the only path to reach here is with non-null value assert value != null; // wrap value with CacheValue (WeakReference) //新建缓存对象并存到reverseMap中 CacheValue<V> cacheValue = new CacheValue<>(value); // put into reverseMap reverseMap.put(cacheValue, Boolean.TRUE); // try replacing us with CacheValue (this should always succeed) if (!valuesMap.replace(subKey, this, cacheValue)) { throw new AssertionError("Should not reach here"); } // successfully replaced us with new CacheValue -> return the value // wrapped by it return value; } }
Objects.requireNonNull(valueFactory.apply(key, parameter)),见方法4详解
方法4:apply 创建代理
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length); //遍历接口 for (Class<?> intf : interfaces) { /* * Verify that the class loader resolves the name of this * interface to the same Class object. */ 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"); } /* * Verify that the Class object actually represents an * interface. */ //校验是否是接口 if (!interfaceClass.isInterface()) { throw new IllegalArgumentException( interfaceClass.getName() + " is not an interface"); } /* * Verify that this interface is not a duplicate. */ //校验接口是否重复 if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } } //包路径 String proxyPkg = null; // package to define proxy class in int accessFlags = Modifier.PUBLIC | Modifier.FINAL; /* * Record the package of a non-public proxy interface so that the * proxy class will be defined in the same package. Verify that * all non-public proxy interfaces are in the same package. */ //这里校验所在包修饰符是否是公共的,如果不是则获取所在包名,后续生成的代理对应需要在当前包下,这样才能引用被代理对象 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"); } } } //如果所在包是公共的,则使用默认路径com.sun.proxy if (proxyPkg == null) { // if no non-public proxy interfaces, use com.sun.proxy package proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } /* * Choose a name for the proxy class to generate. */ //创建序号 long num = nextUniqueNumber.getAndIncrement(); //代理类名称 String proxyName = proxyPkg + proxyClassNamePrefix + num; /* * Generate the specified proxy class. */ //生成代理类流 byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try { //生成Class对象 return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } catch (ClassFormatError e) { /* * A ClassFormatError here means that (barring bugs in the * proxy class generation code) there was some other * invalid aspect of the arguments supplied to the proxy * class creation (such as virtual machine limitations * exceeded). */ throw new IllegalArgumentException(e.toString()); } } }
ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags),见方法5详解
方法5:generateProxyClass
public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) { //var0:代理类名称 var1:接口 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; }
var3.generateClassFile(),见方法6详解
方法6:generateClassFile
private byte[] generateClassFile() { //添加Object对象的hashCode、equals、toString方法 this.addProxyMethod(hashCodeMethod, Object.class); this.addProxyMethod(equalsMethod, Object.class); this.addProxyMethod(toStringMethod, Object.class); //获取接口集 Class[] var1 = this.interfaces; //获取接口数量 int var2 = var1.length; int var3; Class var4; //遍历接口 for(var3 = 0; var3 < var2; ++var3) { //获取当前接口 var4 = var1[var3]; //获取当前接口的所有方法 Method[] var5 = var4.getMethods(); //当前接口方法的数量 int var6 = var5.length; //遍历所有方法,添加到proxyMethods集合中 for(int var7 = 0; var7 < var6; ++var7) { Method var8 = var5[var7]; this.addProxyMethod(var8, var4); } } //获取代理方法迭代器 Iterator var11 = this.proxyMethods.values().iterator(); List var12; //校验方法返回类型 while(var11.hasNext()) { var12 = (List)var11.next(); checkReturnTypes(var12); } Iterator var15; try { //添加构造方法到methods中 this.methods.add(this.generateConstructor()); var11 = this.proxyMethods.values().iterator(); while(var11.hasNext()) { var12 = (List)var11.next(); var15 = var12.iterator(); while(var15.hasNext()) { ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next(); //添加方法名 this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10)); //添加处理后的MethodInfo对象信息 this.methods.add(var16.generateMethod()); } } //添加静态代码块 this.methods.add(this.generateStaticInitializer()); } catch (IOException var10) { throw new InternalError("unexpected I/O Exception", var10); } //后面流程是生成代理对象过程 if (this.methods.size() > 65535) { throw new IllegalArgumentException("method limit exceeded"); } else if (this.fields.size() > 65535) { throw new IllegalArgumentException("field limit exceeded"); } else { this.cp.getClass(dotToSlash(this.className)); this.cp.getClass("java/lang/reflect/Proxy"); var1 = this.interfaces; var2 = var1.length; for(var3 = 0; var3 < var2; ++var3) { var4 = var1[var3]; this.cp.getClass(dotToSlash(var4.getName())); } this.cp.setReadOnly(); ByteArrayOutputStream var13 = new ByteArrayOutputStream(); DataOutputStream var14 = new DataOutputStream(var13); try { var14.writeInt(-889275714); var14.writeShort(0); var14.writeShort(49); this.cp.write(var14); var14.writeShort(this.accessFlags); var14.writeShort(this.cp.getClass(dotToSlash(this.className))); var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy")); var14.writeShort(this.interfaces.length); Class[] var17 = this.interfaces; int var18 = var17.length; for(int var19 = 0; var19 < var18; ++var19) { Class var22 = var17[var19]; var14.writeShort(this.cp.getClass(dotToSlash(var22.getName()))); } var14.writeShort(this.fields.size()); var15 = this.fields.iterator(); while(var15.hasNext()) { ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next(); var20.write(var14); } var14.writeShort(this.methods.size()); var15 = this.methods.iterator(); while(var15.hasNext()) { ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next(); var21.write(var14); } var14.writeShort(0); return var13.toByteArray(); } catch (IOException var9) { throw new InternalError("unexpected I/O Exception", var9); } } }
代理类
通过上述方式,这时候会生成一个字节流的代理类,我们可以看到代理类同样实现了被代理类的接口,而且将其方法都解析成Method 对象,当调用其对应方法时,如work方法,会调用我们自定义的InvocationHandler 处理器的invoke方法,而invoke方法通过反射的方法去调用被代理类的work方法,在invoke方法中我们可以在调用被代理类前完成增强处理
public final class $Proxy0 extends Proxy implements Person { private static Method m1; private static Method m4; private static Method m2; private static Method m3; 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 work() throws { try { return (String)super.h.invoke(this, m4, (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 sleep() 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 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")); m4 = Class.forName("proxy.jdk.Person").getMethod("work"); m2 = Class.forName("java.lang.Object").getMethod("toString"); m3 = Class.forName("proxy.jdk.Person").getMethod("sleep"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }
总结
JDK动态代理的思路就是生成一个实现同个接口的代理类,代理类中拥有被代理类的所有方法,并且会在静态代码块中通过反射的放射解析拿到每个方法对应的Method 对象。代理类中的方法会将对应名称的Method 对象传递给我们自定义的InvocationHandler处理器,调用其invoke方法,而invoke方法中,由于有了Method 对象,我们可以通过反射的放射调用被代理类的方法,并且可以在被调用前增加逻辑处理,达到增强的效果。
通过源码的跟踪,我们知道了无论被代理类实现了什么接口,都可以对应的生成代理类,达到动态的效果。