InvocationHandle的invoke方法[通俗易懂]

InvocationHandle的invoke方法[通俗易懂]在学习代理模式中接触到了动态代理的相关内容,这是AOP的核心内容。先用一个例子说明动态代理的使用//接口(动态代理只能代理接口)publicinterfaceSubject{publicvoidrequest();}//接口实现:实现了Subject的request()方法publicclassRealSubjecti

大家好,又见面了,我是你们的朋友全栈君。

在学习代理模式中接触到了动态代理的相关内容,这是AOP的核心内容。先用一个例子说明 动态代理 的使用

//接口(动态代理只能代理接口)  
public interface Subject {  
      
    public void request();  
}  

//接口实现 :实现了Subject的request()方法  
public class RealSubject implements Subject{  
      
    public void request(){  
        System.out.println("From real subject.");  
    }  
} 

Inb

//实现了InvocationHandler  接口
public class DynamicSubject implements InvocationHandler  
{  
    private Object obj;//这是动态代理的好处,被封装的对象是Object类型,接受任意类型的对象  
  
    public DynamicSubject()  
    {  
    }  
  
    public DynamicSubject(Object obj)  
    {  
        this.obj = obj;  
    }  
  
    
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable  
    {  
        System.out.println("before calling " + method);  
  
        method.invoke(obj, args);  
  
        System.out.println("after calling " + method);  
  
        return null;  
    }  
  
}  
public class Client {  
  
    public static void main(String[] args) throws Throwable{  
        // TODO Auto-generated method stub  
  
        Subject rs=new RealSubject();//这里指定被代理类  
        InvocationHandler ds=new DynamicSubject(rs);  
        Class<?> cls=rs.getClass();  
          
        //生成代理类  ,注意subject是Proxy的子类并且实现了Subject接口的一个类。
          
        Subject subject=(Subject) Proxy.newProxyInstance(  
                cls.getClassLoader(),cls.getInterfaces(), ds);       

}


以上就是动态代理的使用方法,有一点很奇怪,那就是invoke方法是如何被调用的呢? 可以看到在以上代码中并没有invoke的身影,那是因为有关invoke的调用时在Proxy类中,invoke方法并不是给我们显示的调用,查看源码我们可以看到。  

首先看Proxy的静态方法newProxyInstance()

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 = getProxyClass(loader, interfaces);  
  
    /* 
     * Invoke its constructor with the designated invocation handler. 
     */  
    try {  
           /* 
            * Proxy源码开始有这样的定义: 
            * private final static Class[] constructorParams = { InvocationHandler.class }; 
            * cons即是形参为InvocationHandler类型的构造方法 
           */  
        Constructor cons = cl.getConstructor(constructorParams);  
        return (Object) cons.newInstance(new Object[] { h });    //此处返回.
    } catch (NoSuchMethodException e) {  
        throw new InternalError(e.toString());  
    } catch (IllegalAccessException e) {  
        throw new InternalError(e.toString());  
    } catch (InstantiationException e) {  
        throw new InternalError(e.toString());  
    } catch (InvocationTargetException e) {  
        throw new InternalError(e.toString());  
    }  
}  

这个方法实际是利用反射,返回了一个Proxy的子类,实现了指定的接口,返回的类叫做$Proxy0, 这个类包含了invoke的秘密! 请看源码:

public final class $Proxy0 extends Proxy implements Subject {  
    private static Method m1;  
    private static Method m0;  
    private static Method m3;  
    private static Method m2;  
  
    static {  
        try {  
            m1 = Class.forName("java.lang.Object").getMethod("equals",  
                    new Class[] { Class.forName("java.lang.Object") });  
  
            m0 = Class.forName("java.lang.Object").getMethod("hashCode",  
                    new Class[0]);  
  
            m3 = Class.forName("***.RealSubject").getMethod("request",  
                    new Class[0]);  
  
            m2 = Class.forName("java.lang.Object").getMethod("toString",  
                    new Class[0]);  
  
        } catch (NoSuchMethodException nosuchmethodexception) {  
            throw new NoSuchMethodError(nosuchmethodexception.getMessage());  
        } catch (ClassNotFoundException classnotfoundexception) {  
            throw new NoClassDefFoundError(classnotfoundexception.getMessage());  
        }  
    } //static  
  
    public $Proxy0(InvocationHandler invocationhandler) {  
        super(invocationhandler);  
    }  
  
    @Override  
    public final boolean equals(Object obj) {  
        try {  
            return ((Boolean) super.h.invoke(this, m1, new Object[] { obj })) .booleanValue();  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
  
    @Override  
    public final int hashCode() {  
        try {  
            return ((Integer) super.h.invoke(this, m0, null)).intValue();  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
  
    public final void request() {  
        try {  
            super.h.invoke(this, m3, null);  
            return;  
        } catch (Error e) {  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
  
    @Override  
    public final String toString() {  
        try {  
            return (String) super.h.invoke(this, m2, null);  
        } catch (Throwable throwable) {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  
}

该类中利用反射获取到了4个方法,Object类自带的equals,hasCode,toString ,以及接口Subject的唯一方法request,因此当我们在主函数中调用request.xxx(方法名),就是在$Proxy0类中调用相应方法,每个方法中都有 super.h.invoke(this,m3,null);        invoke函数在此起到了作用!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/138722.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • HashMap底层数据结构原理解析[通俗易懂]

    HashMap底层数据结构原理解析[通俗易懂]老师:JDK中我们最常用的一个数据类是HashMap。那么,谁可以回答一下HashMap的底层数据结构原理是什么呢?小明:老师,我知道。众所周知,HashMap是一个用于存储Key-Value键值对的集合,每一个键值对也叫做Entry。这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干。HashMap数组每一个元素的初始值都是Null。…

  • 最常用Python开源框架有哪些?

    最常用Python开源框架有哪些?

    2021年10月11日
  • 设计模式之职责链模式

    相信大家都玩过类似于“斗地主”的纸牌游戏,某人出牌给他的下家,下家看看手中的牌,如果要不起,则将出牌请求转发给他的下家,其下家再进行判断。一个循环下来,如果其他人都要不起该牌,则最初的出牌者可以打出新

    2021年12月28日
  • 2016总结——在路上,我走到哪儿了?

    时间过的很快,2016年就这么的结束了,而我站在2017年的脚步上回顾我的2016年,现在的心情不知道怎么表达,说是百感交集可能太过于夸张,但是内心的那种波澜,在2017年到来之后,越来越强烈。所以我写下今天的这些,这个迟来的总结,让自己心里舒坦一点。

  • Python之struct

    1.功能(1)按照指定格式将Python数据转换为字符串(该字符串为字节流)(2)按照指定格式将字节流转换为Python指定的数据类型(3)处理二进制数据,如果用struct来处理文件的

    2021年12月18日
  • hadoop的简介_hadoop体系

    hadoop的简介_hadoop体系一、概述Hadoop起源:hadoop的创始者是DougCutting,起源于Nutch项目,该项目是作者尝试构建的一个开源的Web搜索引擎。起初该项目遇到了阻碍,因为始终无法将计算分配给多台计算机。谷歌发表的关于GFS和MapReduce相关的论文给了作者启发,最终让Nutch可以在多台计算机上稳定的运行;后来雅虎对这项技术产生了很大的兴趣,并组建了团队开发,从Nutch中剥离出分布式计算模块命名为“Hadoop”。最终Hadoop在雅虎的帮助下能够真正的处理海量的Web数据。…

    2022年10月17日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号