JDK 动态代理之源码解析

过几天我会分享spring AOP 的相关的代理的源码,为了让大家学好springAOP ,今天先分析jdk 的动态代理

1、首先创建一个接口和一个被代理的对象:

package com.nandao.proxy;

public interface People {

    public void zdx();
}
package com.nandao.proxy;

/*
* 被代理实例
* */
public class Nandao implements People {

     //1、nandao找到对象的业务场景
    @Override
    public void zdx() {
        System.out.println("我在北京工作,没有时间找对象!");
    }
    //2、如果父母帮助南道找到了对象等等
}

然后创建一个增强类

package com.nandao.proxy;


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

/*
 * 这个是一个增强类,实现InvocationHandler通用接口,是对目标对象的一个方法增强
 * */
public class ParentInvocationHandler implements InvocationHandler {

    private People people;
    //持有people接口的引用
    public ParentInvocationHandler(People people) {
        this.people = people;
    }

    /*
     * 找到对象以后,帮助南道操持婚礼等
     * */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //帮他找到对象
        before();

        //这个invoke就会掉到被代理类中的method
        method.invoke(people,args);

        after();

        return null;
    }

    /*
     *  这个方法是南道在找到对象之前,父母帮助他做得事情
     * */
    private void before() {
        System.out.println("我是南道父母,我需要帮助他找对象!!");
    }

    /*
     * 找到对象之前,父母帮助他操持婚礼,带小孩
     * */
    private void after() {
        System.out.println("我是南道的父母,我们需要帮助ta操持婚礼,帮他带小孩等等");
    }
}

2、我们写一个测试方法


import sun.misc.ProxyGenerator;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Proxy;

public class TestProxy {
    public static void main(String[] args) {

         //proxy对象就是nandao这个对象的一个代理实例,nandao这个对象就是一个被代理,参数 ClassLoader 是类加载器
         //new Class<?>[]{People.class} 这是接口数组
         //new ParentInvocationHandler(new Nandao())  通用接口实现类持有被代理对象的引用
        People people = (People)Proxy.newProxyInstance(TestProxy.class.getClassLoader(),new Class<?>[]{People.class},
                new ParentInvocationHandler(new Nandao()));

        people.zdx();
        //是否要将生成代理类的字节码.class文件保存到磁盘中,和项目文件在相同目录
        createProxyClassFile();
    }

    public static void createProxyClassFile() {
        //$Proxy0 执行后此class文件生成到项目得我根目录里,比如:D:\spring-source\$Proxy0.class,然后把这个文件直接拉到IDEA中就看到相应的java代码,这个类就是代理类。
        byte[] $Proxy0s = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{People.class});

        try {
            FileOutputStream fileOutputStream = new FileOutputStream("$Proxy0.class");
            fileOutputStream.write($Proxy0s);
            fileOutputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3、执行结果如下,并且生成代理类的class文件

执行过程查看people的类名

 执行测试结果:

4、$Proxy0.class文件直接拉到IDEA中或者通过jd-gui.exe反编译后 如下


import com.enjoy.jack.test.People;
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 People {
    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);
        }
    }
    //核心接口在这里,测试类TestProxy调用people.zdx();就是走的这里
    public final void zdx() 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.enjoy.jack.test.People").getMethod("zdx");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

我们分析代理类中,我们需要被代理的方法zdx()的实现中,都是InvovationHandler中直接调用的invoke方法,如图证明:

 

5、我们追踪一下源码,点击Proxy.newProxyInstance 方法-->

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

    /*
     * 使用指定的调用处理程序调用其构造函数
     */
    try {
        if (sm != null) {
            checkNewProxyPermission(Reflection.getCallerClass(), cl);
        }
        //根据相应的参数获取有参构造函数
        //    private static final Class<?>[] constructorParams = 
        //      {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});//点击进入
    } 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);
    }
}

参数进来

 

继续生成代理类的类名 

获取有参构造函数;

  下个环节开始调用

 进入到这里

@CallerSensitive
public T newInstance(Object ... initargs)
    throws InstantiationException, IllegalAccessException,
           IllegalArgumentException, InvocationTargetException
{
    if (!override) {
        if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
            Class<?> caller = Reflection.getCallerClass();
            checkAccess(caller, clazz, null, modifiers);
        }
    }
    if ((clazz.getModifiers() & Modifier.ENUM) != 0)
        throw new IllegalArgumentException("Cannot reflectively create enum objects");
    //获取构造函数所需要的声明类
    ConstructorAccessor ca = constructorAccessor;   // read volatile
    if (ca == null) {
        ca = acquireConstructorAccessor();//点击进入获取 ca 声明类
    }
    @SuppressWarnings("unchecked")
    T inst = (T) ca.newInstance(initargs);//创建单例实体
    return inst;
}

点击  acquireConstructorAccessor()

  private ConstructorAccessor acquireConstructorAccessor() {
        // First check to see if one has been created yet, and take it
        // if so.
        ConstructorAccessor tmp = null;
        if (root != null) tmp = root.getConstructorAccessor();
        if (tmp != null) {
            constructorAccessor = tmp;
        } else {
            // Otherwise fabricate one and propagate it up to the root
            tmp = reflectionFactory.newConstructorAccessor(this);
            setConstructorAccessor(tmp);
        }

        return tmp;
    }

 参数如图

5、流程总结如下:

 

$Proxy0此代理类在JVM内存里面动态生成,同我们的被代理实例一样实现相同的接口People。

 今天jdk 动态代理解析完了,源码也简要分析了,大家应该也有了初步了解;下一篇,我们自己手写一个自己的动态代理实现业务流程(替换掉JDK的源码),让大家有更深入的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寅灯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值