美文网首页
Spring-8-JDK动态代理

Spring-8-JDK动态代理

作者: 宠辱不惊的咸鱼 | 来源:发表于2019-10-04 09:37 被阅读0次

    JDK动态代理分步使用步骤

    • 通过实现InvocationHandler接口来自定义自己的InvocationHandler(在InvocationHandler初始化对象时绑定target)
    public class HWInvocationHandler implements InvocationHandler {
      private Object target;
      public HWInvocationHandler (Object target) {
        this.target = target;
      }
      public Object invoke(Object proxy, Method method, Object[] args) throws Exception {
        System.out.println("-----插入前置通知代码-----");
        Object re = method.invoke(target, args);
        System.out.println("-----插入后置处理代码-----");
        return rs;
      }
    }
    
    • 通过Proxy.getProxyClass获得动态代理类的Class对象,参数:类加载器,接口列表
    public void test() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
      System.getProperties.put("sun.misc.ProxyGenerator.saveGeneratedFiles","true");
      Class proxyClazz = Proxy.getProxyClass(IHello.class.getClassLoader(), new Class[]{ IHello.class });
      Constructor constructor = proxyClazz.getConstructor(InvocationHandler.class);
      IHello ihello = (IHello) constructor.newInstance(new HWInvocationHandler(new Hello()));
      ihello.sayHello();
    }
    
    • 通过反射机制获得代理类的构造方法,方法签名为getConstructor(InvocationHandler.class)
    • 通过构造函数的newInstance获得代理对象,参数就是自定义的InvocationHandler
    • 通过代理对象调用目标方法,代理对象与目标对象的同名方法中,执行其持有的InvocationHandler(这个对象是在Proxy中声明的属性,被代理类继承过来了)对象的invoke方法
    • 说明
    IHello // 接口
    Hello // 业务实现类业务
    public final class $Proxy0 extends Proxy implements IHello // 生成的代理类$Proxy0
    
    public $Proxy0 (InvocationHandler paramInvocationHandler) {
      super(paramInvocationHandler); //代理类的构造函数直接用父类Proxy的
    }
    protected Proxy (InvocationHandler h) {
      Objects.requireNonNull(h);
      this.h = h;
    }
    

    Proxy.newProxyInstance

    • Proxy中,有一个封装的方法来一步到位的生成代理对象
    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
    IHello ihello = (IHello) Proxy.newProxyInstance(IHello.class.getClassLoader(), new Class[] {IHello.class}, new InvocationHandler(new Hello()));
    ihello.sayHello();
    

    Spring里的代码流程

    • 下面的JDK动态代理原理逻辑分析就以newProxyInstance来展开了,虽然和上面的分步式存在一些代码差别,但原理是一致的
    public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
    
    • Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)
      • this就是JdkDynamicAopProxy本身
      • Class<?> cl = getProxyClass0(loader, intfs);
    • Proxy.getProxyClass0
      • return proxyClassCache.get(loader, interfaces);
    • Weakcache.get
      • V value = supplier.get();
    • WeakCache$Factory.get
      • value = Objects.requireNonNull(valueFactory.apply(key, parameter));
    • Proxy$ProxyClassFactory.apply
      • byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);
    package com.sun.proxy;
    
    import com.fjh.aop.ITarget;
    import com.fjh.aop.ITarget2;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.UndeclaredThrowableException;
    
    public final class $Proxy2 extends Proxy implements ITarget, ITarget2 {
        private static Method m1;
        private static Method m4;
        private static Method m2;
        private static Method m3;
        private static Method m0;
    
        public $Proxy2(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 void target2() throws  {
            try {
                super.h.invoke(this, m4, (Object[])null);
            } catch (RuntimeException | Error var2) {
                throw var2;
            } catch (Throwable var3) {
                throw new UndeclaredThrowableException(var3);
            }
        }
    
        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 target() 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"));
                m4 = Class.forName("com.fjh.aop.ITarget2").getMethod("target2");
                m2 = Class.forName("java.lang.Object").getMethod("toString");
                m3 = Class.forName("com.fjh.aop.ITarget").getMethod("target");
                m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            } catch (NoSuchMethodException var2) {
                throw new NoSuchMethodError(var2.getMessage());
            } catch (ClassNotFoundException var3) {
                throw new NoClassDefFoundError(var3.getMessage());
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Spring-8-JDK动态代理

          本文链接:https://www.haomeiwen.com/subject/sewjpctx.html