以前值是读过一遍jdk和cglib的代理,时间长了,都忘记入口在哪里了,值是记得其中的一些重点了,今天写一篇博客,当作是笔记。和以前一样,关键代码,我会用红色标记出来。
首先,先列出我的jdk代理对象和测试代码:
package com.example.gof.proxy; /** * 买车接口 */ public interface BuyCard { void buycard(); }
package com.example.gof.proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class BuyCardDynamicProxy implements InvocationHandler { private Object object; public BuyCardDynamicProxy(final Object object) { this.object = object; } /** * 代理回调的方法,反编译后可以看到调用的是这段代码:super.h.invoke(this, m3, null); * m3 = Class.forName("com.example.gof.proxy.BuyCard").getMethod("buycard", new Class[0]); * @param proxy 代理 * @param method 代理调用的而方法 * @param args 调用的方法的参数 * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("动态代理,买车前"); Object res= method.invoke(object,args); System.out.println("动态代理,洗刷刷"); return res; } }
package com.example.gof.proxy; import com.example.gof.proxy.impl.BuyCardImpl; import sun.misc.ProxyGenerator; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Proxy; public class TestBuyCardDynamicProxy { public static void main(String[] args) throws IOException { BuyCard buyCard = new BuyCardImpl(); BuyCard buyCardProxy = (BuyCard) Proxy.newProxyInstance(BuyCard.class.getClassLoader(), new Class[]{BuyCard.class}, new BuyCardDynamicProxy(buyCard)); buyCardProxy.buycard();
//下面这段是用于生成字节码分析的 // byte[] classFile= ProxyGenerator.generateProxyClass("$Proxy", new Class<?>[]{BuyCard.class}); // File file=new File("D:\java\GoF\src\main\java\com\example\gof\proxy/$Proxy.class"); // FileOutputStream os=new FileOutputStream(file); // os.write(classFile); // os.flush(); // os.close(); } }
跟踪进去,查看 Proxy.newProxyInstance(BuyCard.class.getClassLoader() 这个方法,代码如下:
/** * Returns an instance of a proxy class for the specified interfaces * that dispatches method invocations to the specified invocation * handler. * 返回一个代理类实例,用于调用响应的接口方法 * <p>{@code Proxy.newProxyInstance} throws * {@code IllegalArgumentException} for the same reasons that * {@code Proxy.getProxyClass} does. * * @param loader the class loader to define the proxy class * @param interfaces the list of interfaces for the proxy class * to implement * @param h the invocation handler to dispatch method invocations to * @return a proxy instance with the specified invocation handler of a * proxy class that is defined by the specified class loader * and that implements the specified interfaces * @throws IllegalArgumentException if any of the restrictions on the * parameters that may be passed to {@code getProxyClass} * are violated * @throws SecurityException if a security manager, <em>s</em>, is present * and any of the following conditions is met: * <ul> * <li> the given {@code loader} is {@code null} and * the caller's class loader is not {@code null} and the * invocation of {@link SecurityManager#checkPermission * s.checkPermission} with * {@code RuntimePermission("getClassLoader")} permission * denies access;</li> * <li> for each proxy interface, {@code intf}, * the caller's class loader is not the same as or an * ancestor of the class loader for {@code intf} and * invocation of {@link SecurityManager#checkPackageAccess * s.checkPackageAccess()} denies access to {@code intf};</li> * <li> any of the given proxy interfaces is non-public and the * caller class is not in the same {@linkplain Package runtime package} * as the non-public interface and the invocation of * {@link SecurityManager#checkPermission s.checkPermission} with * {@code ReflectPermission("newProxyInPackage.{package name}")} * permission denies access.</li> * </ul> * @throws NullPointerException if the {@code interfaces} array * argument or any of its elements are {@code null}, or * if the invocation handler, {@code h}, is * {@code null} */ @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); } /* * 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); } 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); } }
/** * a cache of proxy classes */ private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory()); /** * Generate a proxy class. Must call the checkProxyAccess method * to perform permission checks before calling this. */ 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 return proxyClassCache.get(loader, interfaces); }
上面这个代码当初看了很久,怎么到proxyClassCache.get(loader, interfaces); 就已经生成了代理对象呢。后来百度下,才知道proxyClassCache9 这个对象调用构造参数时候,就生成了二进制文件,核心代码也在这里。继续往下看
/** * A factory function that generates, defines and returns the proxy class given * the ClassLoader and array of interfaces.
* 一个工厂函数,它生成、定义并返回给定类加载器和接口数组的代理类。 */ private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> { // prefix for all proxy class names private static final String proxyClassNamePrefix = "$Proxy"; // next number to use for generation of unique proxy class names 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) { /* * 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"); } } } 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 {
//加载到jvm里,返回代理对象 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)
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; }
由上面可以看见,核心代码,就是生成了二进制字节码文件Files.write(var2, var4, new OpenOption[0]);
为什么我们看不见呢,那是因为被删除了,可以手动生成这个二进制文件(.class后缀的),也就是上面的那段测试代码的例子。
下面是二进制字节码的文件内容:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // import com.example.gof.proxy.BuyCard; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class $Proxy extends Proxy implements BuyCard { private static Method m1; private static Method m2; private static Method m3; private static Method m0; public $Proxy(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 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 void buycard() throws { try { 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")); m2 = Class.forName("java.lang.Object").getMethod("toString"); m3 = Class.forName("com.example.gof.proxy.BuyCard").getMethod("buycard"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }
从上面可以看到,除了自定义的buycard() 方法外,还有toString()、equals()、hashCode() 三个方法。这三个方法是Object 的方法,每个接口、类都会从Object继承这三个方法。当调用buycard()的时候,可以看到调用的是super.h.invoke(xxx) 这样调用的。这里的h,就是我们自定义的,继承了InvocationHandler的类:BuyCardDynamicProxy。
至于invoke方式是怎么调用的,在另外一篇博客https://www.cnblogs.com/drafire/p/9637349.html 继续解析
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
下面看下cglib的代码解读,依然是先贴出测试代码
public class BuyCardCglibProxy implements MethodInterceptor { private Object target; public Object getInstance(final Object target) { this.target = target; Enhancer enhancer=new Enhancer(); enhancer.setSuperclass(target.getClass()); enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("cglib动态代理前"); //这里使用的是methodProxy.invokeSuper,而不是method.invoke //代理类调用父类的方法 Object res= methodProxy.invokeSuper(o,objects); System.out.println("cglib动态代理后"); return res; } }
package com.example.gof.proxy; import com.example.gof.proxy.impl.BuyCardImpl; import org.springframework.cglib.core.DebuggingClassWriter; public class TestBuyCardCglibProxy { public static void main(String[] args) { System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, TestBuyCardCglibProxy.class.getClass().getResource("/").getPath() ); BuyCard buyCard=new BuyCardImpl(); BuyCardCglibProxy proxy=new BuyCardCglibProxy(); BuyCardImpl impl= (BuyCardImpl)proxy.getInstance(buyCard); impl.buycard(); } }
关键代码在:enhancer.create() 这个方法,跟踪进去,代码如下:
public Object create() { this.classOnly = false; this.argumentTypes = null; return this.createHelper(); }
private Object createHelper() { this.preValidate(); Object key = KEY_FACTORY.newInstance(this.superclass != null ? this.superclass.getName() : null, ReflectUtils.getNames(this.interfaces), this.filter == ALL_ZERO ? null : new WeakCacheKey(this.filter), this.callbackTypes, this.useFactory, this.interceptDuringConstruction, this.serialVersionUID); this.currentKey = key; Object result = super.create(key); return result; }
protected Object create(Object key) { try { ClassLoader loader = this.getClassLoader(); //获取加载器 Map<ClassLoader, AbstractClassGenerator.ClassLoaderData> cache = CACHE;
//从缓存中读取 AbstractClassGenerator.ClassLoaderData data = (AbstractClassGenerator.ClassLoaderData)cache.get(loader); if (data == null) { //如果缓存没有对应的数据 Class var5 = AbstractClassGenerator.class; synchronized(AbstractClassGenerator.class) { cache = CACHE; data = (AbstractClassGenerator.ClassLoaderData)cache.get(loader); if (data == null) { Map<ClassLoader, AbstractClassGenerator.ClassLoaderData> newCache = new WeakHashMap(cache); data = new AbstractClassGenerator.ClassLoaderData(loader); //生成二进制字节码 newCache.put(loader, data); CACHE = newCache; } } } this.key = key; Object obj = data.get(this, this.getUseCache());
//生成代理对象 return obj instanceof Class ? this.firstInstance((Class)obj) : this.nextInstance(obj); } catch (RuntimeException var9) { throw var9; } catch (Error var10) { throw var10; } catch (Exception var11) { throw new CodeGenerationException(var11); } }
public ClassLoaderData(ClassLoader classLoader) { if (classLoader == null) { throw new IllegalArgumentException("classLoader == null is not yet supported"); } else { this.classLoader = new WeakReference(classLoader); Function<AbstractClassGenerator, Object> load = new Function<AbstractClassGenerator, Object>() { public Object apply(AbstractClassGenerator gen) { Class klass = gen.generate(ClassLoaderData.this); //核心代码 return gen.wrapCachedClass(klass); } }; this.generatedClasses = new LoadingCache(GET_KEY, load); } }
protected Class generate(AbstractClassGenerator.ClassLoaderData data) { Object save = CURRENT.get(); CURRENT.set(this); Class var8; try { ClassLoader classLoader = data.getClassLoader(); if (classLoader == null) { throw new IllegalStateException("ClassLoader is null while trying to define class " + this.getClassName() + ". It seems that the loader has been expired from a weak reference somehow. Please file an issue at cglib's issue tracker."); } String className; synchronized(classLoader) { className = this.generateClassName(data.getUniqueNamePredicate()); data.reserveName(className); this.setClassName(className); } Class gen; if (this.attemptLoad) { try { gen = classLoader.loadClass(this.getClassName()); Class var25 = gen; return var25; } catch (ClassNotFoundException var20) { ; } } byte[] b = this.strategy.generate(this); //核心代码 className = ClassNameReader.getClassName(new ClassReader(b)); ProtectionDomain protectionDomain = this.getProtectionDomain(); synchronized(classLoader) { if (protectionDomain == null) { gen = ReflectUtils.defineClass(className, b, classLoader); } else { gen = ReflectUtils.defineClass(className, b, classLoader, protectionDomain); } } var8 = gen; } catch (RuntimeException var21) { throw var21; } catch (Error var22) { throw var22; } catch (Exception var23) { throw new CodeGenerationException(var23); } finally { CURRENT.set(save); } return var8; }
//orgspringframeworkspring-core5.0.8.RELEASEspring-core-5.0.8.RELEASE.jar!orgspringframeworkcglibcoreDefaultGeneratorStrategy.class
public byte[] generate(ClassGenerator cg) throws Exception { DebuggingClassWriter cw = this.getClassVisitor(); //从这里的源代码,可以看出,底层是使用asm包的 this.transform(cg).generateClass(cw); return this.transform(cw.toByteArray()); }
//orgspringframeworkspring-core5.0.8.RELEASEspring-core-5.0.8.RELEASE.jar!orgspringframeworkcglibcoreKeyFactory.class public void generateClass(ClassVisitor v) { ClassEmitter ce = new ClassEmitter(v); Method newInstance = ReflectUtils.findNewInstance(this.keyInterface); if (!newInstance.getReturnType().equals(Object.class)) { throw new IllegalArgumentException("newInstance method must return Object"); } else { Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes()); ce.begin_class(46, 1, this.getClassName(), KeyFactory.KEY_FACTORY, new Type[]{Type.getType(this.keyInterface)}, "<generated>"); EmitUtils.null_constructor(ce); EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance)); int seed = 0; CodeEmitter e = ce.begin_method(1, TypeUtils.parseConstructor(parameterTypes), (Type[])null); e.load_this(); e.super_invoke_constructor(); e.load_this(); List<FieldTypeCustomizer> fieldTypeCustomizers = this.getCustomizers(FieldTypeCustomizer.class); int i; for(i = 0; i < parameterTypes.length; ++i) { Type parameterType = parameterTypes[i]; Type fieldType = parameterType; Iterator var11; FieldTypeCustomizer customizer; for(var11 = fieldTypeCustomizers.iterator(); var11.hasNext(); fieldType = customizer.getOutType(i, fieldType)) { customizer = (FieldTypeCustomizer)var11.next(); } seed += fieldType.hashCode(); ce.declare_field(18, this.getFieldName(i), fieldType, (Object)null); e.dup(); e.load_arg(i); var11 = fieldTypeCustomizers.iterator(); while(var11.hasNext()) { customizer = (FieldTypeCustomizer)var11.next(); customizer.customize(e, i, parameterType); } e.putfield(this.getFieldName(i)); } e.return_value(); e.end_method(); e = ce.begin_method(1, KeyFactory.HASH_CODE, (Type[])null); i = this.constant != 0 ? this.constant : KeyFactory.PRIMES[Math.abs(seed) % KeyFactory.PRIMES.length]; int hm = this.multiplier != 0 ? this.multiplier : KeyFactory.PRIMES[Math.abs(seed * 13) % KeyFactory.PRIMES.length]; e.push(i); for(int i = 0; i < parameterTypes.length; ++i) { e.load_this(); e.getfield(this.getFieldName(i)); EmitUtils.hash_code(e, parameterTypes[i], hm, this.customizers); } e.return_value(); e.end_method(); e = ce.begin_method(1, KeyFactory.EQUALS, (Type[])null); Label fail = e.make_label(); e.load_arg(0); e.instance_of_this(); e.if_jump(153, fail); int i; for(i = 0; i < parameterTypes.length; ++i) { e.load_this(); e.getfield(this.getFieldName(i)); e.load_arg(0); e.checkcast_this(); e.getfield(this.getFieldName(i)); EmitUtils.not_equals(e, parameterTypes[i], fail, this.customizers); } e.push(1); e.return_value(); e.mark(fail); e.push(0); e.return_value(); e.end_method(); e = ce.begin_method(1, KeyFactory.TO_STRING, (Type[])null); e.new_instance(Constants.TYPE_STRING_BUFFER); e.dup(); e.invoke_constructor(Constants.TYPE_STRING_BUFFER); for(i = 0; i < parameterTypes.length; ++i) { if (i > 0) { e.push(", "); e.invoke_virtual(Constants.TYPE_STRING_BUFFER, KeyFactory.APPEND_STRING); } e.load_this(); e.getfield(this.getFieldName(i)); EmitUtils.append_string(e, parameterTypes[i], EmitUtils.DEFAULT_DELIMITERS, this.customizers); } e.invoke_virtual(Constants.TYPE_STRING_BUFFER, KeyFactory.TO_STRING); e.return_value(); e.end_method(); ce.end_class(); } }