当前位置: 首页 > news >正文

南京制作网站培训学校网站建设入固定资产

南京制作网站培训学校,网站建设入固定资产,保定网络公司网站,模板网点地址信息获取错误:抖音默认地址未设置!在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的&#xff1a…

在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的:

InvocationHandler:

InvocationHandler is the interface implemented by the invocation handler of a proxy instance. Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:

Object invoke(Object proxy, Method method, Object[] args) throws Throwable

我们看到这个方法一共接受三个参数,那么这三个参数分别代表什么呢?

Object invoke(Object proxy, Method method, Object[] args) throws Throwableproxy:  指代我们所代理的那个真实对象
method:  指代的是我们所要调用真实对象的某个方法的Method对象
args:  指代的是调用真实对象某个方法时接受的参数

如果不是很明白,等下通过一个实例会对这几个参数进行更深的讲解。

接下来我们来看看Proxy这个类:

Proxy provides static methods for creating dynamic proxy classes and instances, and it is also the superclass of all dynamic proxy classes created by those methods. 

Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,  InvocationHandler h)  throws IllegalArgumentException
Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.

这个方法的作用就是得到一个动态的代理对象,其接收三个参数,我们来看看这三个参数所代表的含义:

复制代码

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentExceptionloader:  一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载interfaces:  一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了h:  一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上

复制代码

好了,在介绍完这两个接口(类)以后,我们来通过一个实例来看看我们的动态代理模式是什么样的:

首先我们定义了一个Subject类型的接口,为其声明了两个方法:

public interface Subject
{public void rent();public void hello(String str);
}

接着,定义了一个类来实现这个接口,这个类就是我们的真实对象,RealSubject类:

复制代码

public class RealSubject implements Subject
{@Overridepublic void rent(){System.out.println("I want to rent my house");}@Overridepublic void hello(String str){System.out.println("hello: " + str);}
}

复制代码

下一步,我们就要定义一个动态代理类了,前面说个,每一个动态代理类都必须要实现 InvocationHandler 这个接口,因此我们这个动态代理类也不例外:

复制代码

public class DynamicProxy implements InvocationHandler
{// 这个就是我们要代理的真实对象private Object subject;//    构造方法,给我们要代理的真实对象赋初值public DynamicProxy(Object subject){this.subject = subject;}@Overridepublic Object invoke(Object object, Method method, Object[] args)throws Throwable{// 在代理真实对象前我们可以添加一些自己的操作System.out.println("before rent house");System.out.println("Method:" + method);// 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用method.invoke(subject, args);// 在代理真实对象后我们也可以添加一些自己的操作System.out.println("after rent house");return null;}}

复制代码

最后,来看看我们的Client类:

复制代码

public class Client {public static void main(String[] args) {// 我们要代理的真实对象Subject realSubject = new RealSubject();//这里指定被代理类 // 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的InvocationHandler handler = new DynamicProxy(realSubject);/** 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数 * 第一个参数 handler.getClass().getClassLoader(),我们这里使用代理类的类加载器,也就是被代理的那个真实对象* 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了 * 第三个参数handler,我们这里将这个代理对象关联到了上方的InvocationHandler 这个对象上*/Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),realSubject.getClass().getInterfaces(), handler);//这里可以通过运行结果证明subject是Proxy的一个实例,这个实例实现了Subject接口  System.out.println(subject instanceof Proxy);  //这里可以看出subject的Class类是$Proxy0,这个$Proxy0类继承了Proxy,实现了Subject接口  System.out.println("subject的Class类是:"+subject.getClass().toString());  System.out.print("subject中的属性有:");  Field[] field=subject.getClass().getDeclaredFields();  for(Field f:field){  System.out.print(f.getName()+", ");  }  System.out.print("\n"+"subject中的方法有:");  Method[] method=subject.getClass().getDeclaredMethods();  for(Method m:method){  System.out.print(m.getName()+", ");  }  System.out.println("\n"+"subject的父类是:"+subject.getClass().getSuperclass());  System.out.print("\n"+"subject实现的接口是:");  Class<?>[] interfaces=subject.getClass().getInterfaces();  for(Class<?> i:interfaces){  System.out.print(i.getName()+", ");  }  System.out.println(subject.getClass().getName());System.out.println("\n\n"+"运行结果为:");subject.rent();subject.hello("world");}
}

复制代码

我们先来看看控制台的输出:

复制代码

true
subject的Class类是:class com.sun.proxy.$Proxy0
subject中的属性有:m1, m4, m0, m3, m2, 
subject中的方法有:equals, toString, hashCode, rent, hello, 
subject的父类是:class java.lang.reflect.Proxysubject实现的接口是:com.emuii.proxy.Subject, com.sun.proxy.$Proxy0
运行结果为:
before rent house
Method:public abstract void com.emuii.proxy.Subject.rent()
I want to rent my house
after rent housebefore rent house
Method:public abstract void com.emuii.proxy.Subject.hello(java.lang.String)
hello: world
after rent house

复制代码

我们首先来看看 $Proxy0 这东西,我们看到,这个东西是由 System.out.println(subject.getClass().getName()); 这条语句打印出来的,那么为什么我们返回的这个代理对象的类名是这样的呢?

Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);

可能我以为返回的这个代理对象会是Subject类型的对象,或者是InvocationHandler的对象,结果却不是,首先我们解释一下为什么我们这里可以将其转化为Subject类型的对象?原因就是在newProxyInstance这个方法的第二个参数上,我们给这个代理对象提供了一组什么接口,那么我这个代理对象就会实现了这组接口,这个时候我们当然可以将这个代理对象强制类型转化为这组接口中的任意一个,因为这里的接口是Subject类型,所以就可以将其转化为Subject类型了。

同时我们一定要记住,通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号

接着我们来看看这两句 

subject.rent();
subject.hello("world");

这里是通过代理对象来调用实现的那种接口中的方法,这个时候程序就会跳转到由这个代理对象关联到的 handler 中的invoke方法去执行,而我们的这个 handler 对象又接受了一个 RealSubject类型的参数,表示我要代理的就是这个真实对象,所以此时就会调用 handler 中的invoke方法去执行:

复制代码

public Object invoke(Object object, Method method, Object[] args)throws Throwable{//  在代理真实对象前我们可以添加一些自己的操作System.out.println("before rent house");System.out.println("Method:" + method);//    当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用method.invoke(subject, args);//  在代理真实对象后我们也可以添加一些自己的操作System.out.println("after rent house");return null;}

复制代码

我们看到,在真正通过代理对象来调用真实对象的方法的时候,我们可以在该方法前后添加自己的一些操作,同时我们看到我们的这个 method 对象是这样的:

public abstract void com.xiaoluo.dynamicproxy.Subject.rent()public abstract void com.xiaoluo.dynamicproxy.Subject.hello(java.lang.String)

正好就是我们的Subject接口中的两个方法,这也就证明了当我通过代理对象来调用方法的时候,起实际就是委托由其关联到的 handler 对象的invoke方法中来调用,并不是自己来真实调用,而是通过代理的方式来调用的。

这就是我们的java动态代理机制

http://www.dtcms.com/a/579275.html

相关文章:

  • Linux驱动开发笔记(十九)——IIC(AP3216C驱动+MPU6050驱动)
  • 要在 WPF 中实现数据表对应实体的属性与 UI 控件的双向绑定,并支持修改通知和 UI 自动更新
  • v4l2 subdev 设备节点和属性创建过程
  • (论文速读)基于图像堆栈的低频超宽带SAR叶簇隐蔽目标变化检测
  • 懒人之家网站模板做网站的实践报告
  • 网站建设去哪网站注册商标
  • 垂直越权和水平越权是什么
  • 过关斩将编程题
  • 做自己看视频的网站wordpress网站备份
  • html制作手机网站做网络课堂的平台有哪些网站
  • 进程一、进程基本概念
  • 供求信息网站开发背景计算机软件开发培训机构
  • 如何做照片ppt模板下载网站微信公众平台开发者工具
  • 营销型网站建设细节东莞市建设厅官方网站
  • 网站开发合同技术目标专门做简历的网站软件
  • 4G车联网终端TBOX知识详解
  • 郑州本地做团购的网站wordpress获取自定义文章分类名
  • 自己做的网站别人怎么上网找到合作在惠州做网站
  • 中国建设银行网站密码是什么做淘宝电商比较厉害的网站
  • RFID 技术赋能汽车零件装配线:智能化升级的关键引擎
  • 1、prometheus基础理论
  • 设计社交网站手机可以建网站吗
  • 响应式网站要多久手机站点cn
  • 网站鼠标悬停动态效果古田路9号设计网站
  • 突破 GEO 优化瓶颈:孟庆涛引领的 AI 时代营销新范式
  • 网站模版编辑器企业简介范文
  • 基于Vue的智慧楼宇报修平台设计与实现066z15wb(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • php网站开发套模板步骤张家界城乡建设网站
  • 一元云购网站建设教程wordpress侧边栏插件
  • 惠州城市建设建筑网站cms网站开发网站模板