在学习代理模式中接触到了动态代理的相关内容,这是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函数在此起到了作用!

InvocationHandle的invoke方法相关推荐

  1. Dispatcher.Invoke方法

    前一篇小猪分享过在WPF中简单的使用BackgroundWorker完成多线程操作!在那篇中小猪利用了BackgroundWorker组件对耗时比较多的操作放在了单独的BackgroundWorker ...

  2. JAVA深入研究——Method的Invoke方法。

    在写代码的时候,发现Method可以调用子类的对象,但子类即使是改写了的Method,方法名一样,去调用父类的对象也会报错,虽然这是很符合多态的现象,也符合java的动态绑定规范,但还是想弄懂java ...

  3. invokeRequired属性和 invoke()方法

    zt: http://www.x2blog.cn/jinhong618/?tid=22389 问: f (this.InvokeRequired)             {              ...

  4. invoke 数组_对于反射中的invoke()方法的理解

    作者:码上猿梦http://cnblogs.com/daimajun/p/6545533.html 推荐阅读(点击即可跳转阅读) 1. SpringBoot内容聚合 2. 面试题内容聚合 3. 设计模 ...

  5. InvocationHandler的invoke方法如何被调用?

    关键问题是它们内在的联系.虽然可以看源代码,包括类库.但是把它们抽象出来,有助于理解. 在客户类(即以下代码的Client类),语句Manager managerProxy =   (Manager) ...

  6. invoke方法是做啥的_使用 NLog 给 Asp.Net Core 做请求监控

    为了减少由于单个请求挂掉而拖垮整站的情况发生,给所有请求做统计是一个不错的解决方法,通过观察哪些请求的耗时比较长,我们就可以找到对应的接口.代码.数据表,做有针对性的优化可以提高效率.在 asp.ne ...

  7. invoke方法_JVM是如何执行方法调用的?

    前不久在写代码的时候,我不小心踩到一个可变长参数的坑.你或许已经猜到了,它正是可变长参数方法的重载造成的. 我把踩坑的过程放在了文稿里,你可以点击查看. void invoke(Object obj, ...

  8. 深入理解Java中的反射机制和使用原理!详细解析invoke方法的执行和使用

    反射的概念 反射:Refelection,反射是Java的特征之一,允许运行中的Java程序获取自身信息,并可以操作类或者对象的内部属性 通过反射,可以在运行时获得程序或者程序中的每一个类型的成员活成 ...

  9. 反射之invoke方法

    当获得类对应的Class对象后,可以通过getMethods()方法得到全部方法--返回Method数组,或者getMethod()方法来获取指定方法--Method对象. 可以通过Method对象的 ...

最新文章

  1. 如何使用 UserAccountControl 标志操纵用户帐户属性
  2. 用Xwt构建跨平台应用程序[转载]
  3. stylus导入时 报错These relative modules were not found
  4. 20个Flutter实例视频教程-第03节: 不规则底部工具栏制作-1
  5. linux-用户管理190919
  6. 《pytorch》对CIFAR数据集的分类
  7. python tkinter画笑脸_python – 如何在tkinter窗口中绘制图像
  8. Android GridView如何适配不同屏幕
  9. python 成员运算符_Python的“ in”和“ not in”成员资格运算符
  10. Windows下的命令行。
  11. 【ESRI论坛6周年征文】ArcEngine注记(Anno/ Label/Element等)处理专题 -入门篇
  12. HTML5+CSS大作业——清新春暖花开个人博客网站(6页)
  13. android手机内存单位 吉字节,内存容量单位换算(手机内存单位大小排列换算)
  14. 开发部程序员绩效考核办法
  15. 【VBA研究】智力游戏-蓝色方块
  16. iconst、bipush、sipush、ldc指令的区别
  17. 分享一个颜色渐变的网站
  18. 安装win 7 + ubuntu 16.04 双系统安装
  19. 更名通知 || 初心未改,只为更好,好嗨游戏来了
  20. ET199加密方案——文件MD5校验

热门文章

  1. 怎么将迅捷思维导图添加小表情
  2. 2017年4月9日 星期日 --出埃及记 Exodus 25:7
  3. 三态门有一个信号控制端en_单片机基础电路
  4. 华硕路由ax86u 梅林_“亮眼”功能体验!华硕新品路由RT-AX86U评测
  5. 面向物联网的 23 个开源软件项目
  6. 【代码】QQ群最近聊天记录做成词云
  7. excel表格打印每页都有表头_Excel表格技巧—解决打印没有表格线的问题
  8. 主成分分析 PCA 应用实例 鸢尾花数据集
  9. 邮件服务器 之 利用debian sarge和postfix 2.1构建媲美ISP的邮件系统
  10. Failed to decode downloaded font