JDK动态代理【3】Proxy类和InvocationHandler类源码

一、Proxy类,java.lang.reflect.Proxy

* {@code Proxy} provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods.

Proxy类主要有如下功能:

1.为外部实现代理提供接口

public static Object newProxyInstance(ClassLoader loader,  Class[] interfaces, InvocationHandler h)

2.管理缓存,代理类会缓存已经生成的代理类,是一个Key Value结构,而此结构的Key是有ClassLoader和interfaces共同决定的。

3.检查代理类的各项权限。

二、Proxy类的newProxyInstance方法

方法主要是调用 getProxyClass0方法获取代理类,缓存中有则取出,没有则调用ProxyFactory创建。

@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() {

                    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);

        }

    }

三、Proxy类的 getProxyClass0 方法

主要从weakcache中获取Class,weakcache传入了valueFactory(ProxyClassFactory实例),而当weakCache中没有Class时,会调用ProxyClassFactory中的apply生成。

/**

    * 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);

    }

四、ProxyClassFactory类的apply 方法

方法中会先获取到类的package,而后调用  byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags);生成字节码文件。

@Override

        public Class apply(ClassLoader loader, Class[] interfaces) {

            Map, 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 {

                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());

            }

        }

五、InvocationHandler 类

提供接口供代理使用者使用,实现invoke方法,在其中嵌入相应的代码。

public interface InvocationHandler {

    public Object invoke(Object proxy, Method method, Object[] args)

        throws Throwable;

}

你可能感兴趣的:(JDK动态代理【3】Proxy类和InvocationHandler类源码)