九、spring aop之jdk动态代理

使用

动态代理有两个对象,目标对象和代理对象。使用JDK动态代理,目标对象必须实现一个接口。

public class JdkDynamicProxyTest {

    interface IPerson {
        void say() ;
    }

    static class Person implements IPerson {
        @Override
        public void say() {
            System.out.println("hello world");
        }
    }

    static class JdkProxy implements InvocationHandler {

        //目标对象
        private Object target;

        //得到代理对象
        public Object getProxy(Object target) {
            this.target = target;
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(), this);
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("say before");
            method.invoke(target, args);
            System.out.println("say after");
            return null;
        }
    }

    public static void main(String[] args) {
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        JdkProxy jdkProxy = new JdkProxy();
        IPerson person = (IPerson) jdkProxy.getProxy(new Person());
        person.say();
    }
}

原理

要查看JDK动态代理原理,只需要在运行的时候,增加下面一句话:

 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");

会在项目路径下生成一个$Proxy0.class文件,反编译这个文件,就能够明白JDK动态代理原理。

final class $Proxy0 extends Proxy implements IPerson {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(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 say() 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.ming.aop.IPerson").getMethod("say");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

代理的大概结构包括4部分:
静态字段:被代理的接口所有方法都有一个对应的静态变量;
静态块:主要是通过反射初始化静态变量;
具体每个代理方法:逻辑都差不多就是 h.invoke,h是Proxy的属性。主要是调用我们定义好的invocatinoHandler逻辑,触发目标对象target上对应的方法;

public class Proxy implements java.io.Serializable {
    protected InvocationHandler h;
}

构造函数:从这里传入我们InvocationHandler逻辑;构造函数在newProxyInstance方法中通过反射调用。

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

protected Proxy(InvocationHandler h) {
    Objects.requireNonNull(h);
    this.h = h;
}

你可能感兴趣的:(九、spring aop之jdk动态代理)