JDK动态代理

发布时间:2019-06-25 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了JDK动态代理脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

用户在调用被动态代理过的对象的方法时,调用的请求会被自动发给代理对象(实现了InvocationHandler接口)的invoke()方法,由invoke()方法来实现对请求的统一处理。

源码分析

public class Proxy implements java.io.Serializable {
private static final Class<?>[] constructorParams =  { InvocationHandler.class };
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
......

    @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
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }
            //getConstructor(InvocationHandler.class) 获取代理类的构造器
            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});
        }  
    ......
}

 

private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // key为WeakReference,若缓存中存在相同key,则返回ProxyClass,若不存在,则用ProxyClassFactory创建ProxyClass。
        return proxyClassCache.get(loader, interfaces);  //java.lang.reflect.WeakCache 这个内核分析?
    }
......
 }
private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> {
        // 所有代理类ProxyClass名字的前缀 
        private static final String proxyClassNamePrefix = "$Proxy";

        // 用计数器生成代理类ProxyClass的名字
        private static final AtomicLong nextUniqueNumber = new AtomicLong();

        @Override
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
//对每一个interface Class进行验证
            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.
  * 用IdentityHashMap来验证interface Class的唯一性,因为IdentityHashMap的key比较是==,即比较内存地址。
                 */
                if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
                    throw new IllegalArgumentException(
                        "repeated interface: " + interfaceClass.getName());
                }
            }

            String proxyPkg = null;      
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

            // 对于非公共接口,ProxyClass的包名设置为接口的包名    
            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");
                    }
                }
            }

            // 对于公共接口,ProxyClass的包名为com.sun.proxy  
            if (proxyPkg == null) {
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            long num = nextUniqueNumber.getAndIncrement();
            //ProxyClass的完全限定名
            String proxyName = proxyPkg + proxyClassNamePrefix + num;

            //由c++写的ProxyGenerator生成代理类的二进制字节码
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
                // 根据二进制字节码返回相应的ProxyClass  
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {               
                throw new IllegalArgumentException(e.toString());
            }
        }
}

$Proxy.class

以下是反编译$Proxy0.class:

public final class $Proxy0 extends Proxy implements MyInterface1{  
  private static ;method m1;  
  private static Method m3;  
  private static Method m0;  
  private static Method m2;  
 
  public $Proxy0(InvocationHandler paraminvocationHandler) {  
    super(paramInvocationHandler);  
  }  
  
  public final boolean equals(Object paramObject) {  
    try {  
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();  
    }  
    catch (Error|RuntimeException localError) {  
      throw localError;  
    }  
    catch (Throwable localThrowable) {  
      throw new UndeclaredThrowableException(localThrowable);  
    }  
  }  
  
  public final void sayHello(String paramString) {  
    try {  
      this.h.invoke(this, m3, new Object[] { paramString });  
      return;  
    }  
    catch (Error|RuntimeException localError) {  
      throw localError;  
    }  
   catch (Throwable localThrowable) {  
      throw new UndeclaredThrowableException(localThrowable);  
    }  
  }  

  
  public final int hashCode() {  
    try {  
      return ((Integer)this.h.invoke(this, m0, null)).intValue();  
    }  
    catch (Error|RuntimeException localError) {  
      throw localError;  
    }  
    catch (Throwable localThrowable) {  
      throw new UndeclaredThrowableException(localThrowable);  
    }  
  }  
  
  public final String toString() {  
    try {  
        return (String)this.h.invoke(this, m2, null);  
    }  
    catch (Error|RuntimeException localError) {  
      throw localError;  
    }  
    catch (Throwable localThrowable) {  
      throw new UndeclaredThrowableException(localThrowable);  
    }  
  }  
  
  static {  
    try {  
      m1 = Class.forName("java.lang.Object").getMethod("equals"new Class[] { Class.forName("java.lang.Object") });  
      m3 = Class.forName("com.mikan.proxy.MyInterface1").getMethod("sayHello"new Class[] { Class.forName("java.lang.String") });  
      m0 = Class.forName("java.lang.Object").getMethod("hashCode"new Class[0]);  
    m2 = Class.forName("java.lang.Object").getMethod("toString"new Class[0]);  
      return;  
    }  
    catch (NoSuchMethodException localNoSuchMethodException) {  
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());    }  
    catch (ClassNotFoundException localClassNotFoundException) {  
      throw new NoClaSSDefFoundError(localClassNotFoundException.getMessage());  
    }  
  }  
} 

 

$Proxy0.class的总结:

  1. 对于要代理没有接口的类,则必须继承该没有接口的类,从而覆盖其方法,但由于java不能多继承,这里代理类已经继承了Proxy类了,不能再继承其他的类,所以JDK的动态代理不支持对实现类的代理,只支持接口的代理。

  2. 构造方法的入参为InvocationHandler,这说明该代理类是实现了InvocationHandler接口的类的代理类,而InvocationHandler实现类再代理真正的实体类

  3. 静态代码块会初始化真正实体类的Method对象,以及Object类的equals、hashCode、toString的Method对象


总结:
Proxy 会从内部类WeakCache中根据ClassLoader 和interfaces获取ProxyClass(若缓存中存在相同key,则返回ProxyClass,若不存在,则用ProxyClassFactory创建ProxyClass(由ProxyGenerator生成二进制码,再将写成*.class文件))。


AOP JDK动态代理实现

切面InvocationHandler:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
    // BeforeAdvice  
    Object retVal = null;  
    try {  
        retVal = method.invoke(target, args);  // AroundAdvice 代替该语句      
        // AfterReturningAdvice  
    }  
    catch (Throwable e) {  
        // AfterThrowingAdvice  
    }  
    finally {  
        //finally块一定会在return前面执行。
        // AfterAdvice  
    }  
    return retVal;  
}  

脚本宝典总结

以上是脚本宝典为你收集整理的JDK动态代理全部内容,希望文章能够帮你解决JDK动态代理所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。