动态代理(jdk)

一,动态代理的作用
首先来看静态代理,静态代理包括三个角色,抽象角色,真实角色,代理角色。真实角色实现主要的业务逻辑;代理角色将真实角色封装,同时可以添加日志,缓存,权限管理等业务。静态代理将主要业务逻辑和其他业务分层次管理,降低了耦合,易于管理和维护。
当静态代理类中的方法越来越多,每个方法中的缓存等业务需要的重复代码越来越多,这时候就引入了动态代理。
所以动态代理的作用:对业务进行逻辑分层管理,降低耦合;减少了静态代理造成的代码冗余
二,动态代理的使用及原理

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxy {

    public static void main(String[] args) {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        InvocationHandler handler = new InvocationHandler() {
            ProxyInstance instance = new ProxyInstance();
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                System.out.println("对" + method.getName() + "的额外操作");
                return method.invoke(instance, args);
            }
        };
        Interface1 obj = (Interface1) Proxy.newProxyInstance(Interface1.class.getClassLoader(),
                new Class[] { Interface1.class, Interface2.class},
                handler);
        obj.method1();
        @SuppressWarnings("unchecked")
        Class<Interface1> class2 = (Class<Interface1>) Proxy.getProxyClass(Interface1.class.getClassLoader(),
                new Class[] { Interface1.class, Interface2.class});
        System.out.println(obj.getClass() == class2);
    }
}

interface Interface1 {
    void method1();
}

interface Interface2 {
    void method2();
}

class ProxyInstance implements Interface1, Interface2 {

    @Override
    public void method2() {
        System.out.println("method2");
    }

    @Override
    public void method1() {
        System.out.println("method1");
    }
}

什么原理呢,直接点进去看jdk源码

 public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        if (h == null) {
            throw new NullPointerException();
        }

        /*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, interfaces); // stack walk magic: do not refactor

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            SecurityManager sm = System.getSecurityManager();
            if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
                // create proxy instance with doPrivilege as the proxy class may
                // implement non-public interfaces that requires a special permission
                return AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    public Object run() {
                        return newInstance(cons, ih);
                    }
                });
            } else {
                return newInstance(cons, ih);
            }
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString());
        }
    }

发现是获取一个Class类,然后通过构造器来实例化,再看一下获取Class类的方法,

/*
     * Class的缓存机制:
     * //loaderToCache  Map<ClassLoader, Map<List<String>, Object>> weakHashMap
     * //cache map<interfaces, class>
     * //loaderToCache  Map<ClassLoader, map<interfaces, class>>
     */
    private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        //接口的各种校验,省略

        Class<?> proxyClass = null;

        //interfaceNames 包含所有接口名称的list
        List<String> key = Arrays.asList(interfaceNames);

        Map<List<String>, Object> cache;
        synchronized (loaderToCache) {
            cache = loaderToCache.get(loader);
            if (cache == null) {
                cache = new HashMap<>();
                loaderToCache.put(loader, cache);
            }
        }

        //在缓存中寻找class,
        synchronized (cache) {
            //这个循环比较巧妙
            do {
                Object value = cache.get(key);
                if (value instanceof Reference) {
                    proxyClass = (Class<?>) ((Reference) value).get();
                }
                if (proxyClass != null) {
                    // proxy class already generated: return it
                    return proxyClass;
                } else if (value == pendingGenerationMarker) {
                    // proxy class being generated: wait for it
                    try {
                        cache.wait();
                    } catch (InterruptedException e) {
                    }
                    continue;
                } else {
                    cache.put(key, pendingGenerationMarker);
                    break;
                }
            } while (true);
        }

        try {
            String proxyPkg = null;     // package to define proxy class in
            //校验接口:非public接口必须在同一包下
            //获取包路径
            for (int i = 0; i < interfaces.length; i++) {
                int flags = interfaces[i].getModifiers();
                if (!Modifier.isPublic(flags)) {
                    String name = interfaces[i].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 sun.proxy package
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            {
                long num;
                //同步
                synchronized (nextUniqueNumberLock) {
                    num = nextUniqueNumber++;
                }
                String proxyName = proxyPkg + proxyClassNamePrefix + num;

                //ProxyGenerator.generateProxyClass生成 类文件的二进制数据流,包含在byte数组中
                //静态方法,那就可以直接调用次方法生成二进制数据流
                byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                    proxyName, interfaces);
                try {
                    //通过btye数据,生产了class
                    proxyClass = defineClass0(loader, proxyName,
                        proxyClassFile, 0, proxyClassFile.length);
                } catch (ClassFormatError e) {
                    throw new IllegalArgumentException(e.toString());
                }
            }
            // add to set of all generated proxy classes, for isProxyClass
            proxyClasses.put(proxyClass, null);

        } finally {
            synchronized (cache) {
                if (proxyClass != null) {
                    cache.put(key, new WeakReference<Class<?>>(proxyClass));
                } else {
                    cache.remove(key);
                }
                cache.notifyAll();
            }
        }
        return proxyClass;
    }

Class类原来是在运行时生成的。
将生成的class类文件$proxy0反编译后得到如下

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy
  implements Interface1, Interface2
{
  private static Method m1;
  private static Method m3;
  private static Method m4;
  private static Method m0;
  private static Method m2;

  public $Proxy0(InvocationHandler paramInvocationHandler)
    throws 
  {
    super(paramInvocationHandler);
  }

  public final boolean equals(Object paramObject)
    throws 
  {
    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 method1()
    throws 
  {
    try
    {
      //执行方法是实际是将方法委托给InvocationHandler的invoke方法来执行
      this.h.invoke(this, m3, null);
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final void method2()
    throws 
  {
    try
    {
      this.h.invoke(this, m4, null);
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final int hashCode()
    throws 
  {
    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()
    throws 
  {
    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
      m3 = Class.forName("Interface2").getMethod("method1", new Class[0]);
      m4 = Class.forName("Interface2").getMethod("method2", new Class[0]);
      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());
    }
  }
}

JDK中的动态代理原理,一目了然。

总结:动态代理(JDK)的原理是在运行时生成类字节码(proxy有缓存机制),然后通过反射获取实例。对实例中将方法的调用将委托给InvocationHandler的invoke方法。动态代理(JDK)只能对实现了接口的类生成代理,而不能针对类,因为生成的类需要继承proxy。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值