1. 程式人生 > >jdk代理和cglib代理源代碼之我見

jdk代理和cglib代理源代碼之我見

import emp pub fix efault 代理 rest mean violate

以前值是讀過一遍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;
    }
//org\springframework\spring-core\5.0.8.RELEASE\spring-core-5.0.8.RELEASE.jar!\org\springframework\cglib\core\DefaultGeneratorStrategy.class
public
byte[] generate(ClassGenerator cg) throws Exception { DebuggingClassWriter cw = this.getClassVisitor(); //從這裏的源代碼,可以看出,底層是使用asm包的 this.transform(cg).generateClass(cw); return this.transform(cw.toByteArray()); }
//org\springframework\spring-core\5.0.8.RELEASE\spring-core-5.0.8.RELEASE.jar!\org\springframework\cglib\core\KeyFactory.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();
            }
        }

jdk代理和cglib代理源代碼之我見