java动态代理机制
2016-07-15 09:22
417 查看
Java动态代理中有两个重要的接口跟类,即 InvoctionHandler(Interface)、DynamicProxy(class),这个接口跟类使我们应用动态代理时必须要用的。每一个动态代理类都必须去实现 InvoctionHandler 这个接口,而且每个代理类的实例都必须关联一个 Hanlder 通过代理对象调用被代理对象中的方法时,其实是代理对象委托 InvoctionHandler 中的 invoke() 方法去调用被代理对象中的方法。invoke()方法的语法:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable 其中三个参数的具体说明如下: proxy: 指代我们所代理的那个真实对象 method: 指代的是我们所要调用真实对象的某个方法的Method对象 args: 指代的是调用真实对象某个方法时接受的参数Proxy 这个类提供了许多方法,其中我们最常用到的是 newProxyInstance 这个方法,这个方法作用就是得到一个动态代理的实例:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentExceptionloader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载interfaces: 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了h: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上我们来看一个例子,手机按我们定义了一个 Subject 接口,这个接口声明了真实对象和代理对象的共同接口,作用是在任何可以使用真实对象的时候都可以使用代理对象:package proxy1;public interface Subject {void rent();void Hello(String str);}接下来要定义一个真实类来实现这个接口:package proxy1;public class RealSubject implements Subject {@Overridepublic void rent() {System.out.println("I want to rent a house!");}@Overridepublic void Hello(String str) {System.out.println("Hello " + str);}}这个真实类中具体实现了抽象接口中定义的方法。接下来就要定义动态代理类了,这个动态代理类必须实现 InvocationHandler 接口:package proxy1;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class DynamicProxy implements InvocationHandler {private Object subject;public DynamicProxy(Object subject) {this.subject = subject;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("Before rent a house,you need to know the proxyObject name.");System.out.println("The proxyObject name is: " + method.getName());method.invoke(subject, args);System.out.println("Now you can live in your new house.");return null;}} 代理类中含有对真实类的引用,从而可以在任何时刻操作真实对象。代理类提供一个与真实类相同的接口,以便在任何时候都可以代理真实类,控制对真是类引用,负责在需要的时候创建真实类对象或者删除真实类对象。代理类通常在将客户端调用传递给真实类之前或者之后,都要执行特定操作,比如日志记录等等,而不是单纯地将调用传递给真实类。最后我们还要定义一个客户端:package proxy1;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class Client {public static void main(String[] args) {Subject subject=new RealSubject(); //创建一个真实对象的引用InvocationHandler handler=new DynamicProxy(subject); //将真实对象的引用传递给代理对象Subject str=(Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(),subject.getClass().getInterfaces(), handler); //代理对象调用真实对象的方法,通过 Proxy.newProxyInstance 创建的//代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,//也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,//以$开头,proxy为中,最后一个数字表示对象的标号。str.rent();str.Hello("Tom");}}控制台输出:Before rent a house,you need to know the proxyObject name.The proxyObject name is: rentI want to rent a house!Now you can live in your new house.Before rent a house,you need to know the proxyObject name.The proxyObject name is: HelloHello TomNow you can live in your new house.str.rent();str.Hello("Tom");这里是通过代理对象来调用实现的那种接口中的方法,这个时候程序就会跳转到由这个代理对象关联到的 handler 中的invoke方法去执行,而我们的这个 handler 对象又接受了一个 RealSubject类型的参数,表示我要代理的就是这个真实对象,所以此时就会调用 handler 中的invoke方法去执行:public Object invoke(Object object, Method method, Object[] args)throws Throwable{// 在代理真实对象前我们可以添加一些自己的操作System.out.println("Before rent a house,you need to know the proxyObject name.");System.out.println("The proxyObject name is: " + method.getName());// 当代理对象调用真实对象的方法时,其会自动的跳转到代理对象关联的handler对象的invoke方法来进行调用method.invoke(subject, args);// 在代理真实对象后我们也可以添加一些自己的操作System.out.println("Now you can live in your new house.");return null;}调用的就是我们的Subject接口中的两个方法,这也就证明了当我通过代理对象来调用方法的时候,实际就是委托由其关联到的 handler 对象的invoke方法中来调用,并不是自己来真实调用,而是通过代理的方式来调用的。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树