首页 > 代码库 > java动态代理模式

java动态代理模式

java动态代理机制详解

Spring的核心AOP的原理就是java的动态代理机制。

在java的动态代理机制中,有两个重要的类或接口:

1.InvocationHandler(Interface):

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

InvocatonHandler这个接口的invoke方法来进行调用。

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

 

proxy:代表我们所代理的那个真实对象;

method:只带我们所要调用真实对象的某个方法的Method对象;

args:指代的是调用真实对象某个方法时接受的参数。

2.Proxy(Class)

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

 1 public static Object newProxyInstance(ClassLoader loader,Class<?>[] interface,InvocationHandler h)throws IllegalArgumentException 

loader:一个ClassLoder对象,定义了由那个ClassLoader对象来对生成的代理对象进行加载;

interface:一个Interface对象的数组,表示的是我将要给我的需要代理的对象提供一组什么借口,如果我提供了一组借口给他,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了;

h:一个InvocationHandler对象,表示的是当我这个代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上。

  

【代码清单--1】抽象对象角色:

 1 package com.huawei.subject; 2 /** 3  * 抽象对象角色 4  * @author Administrator 5  * 6  */ 7 public interface Subject  8 { 9     void rent();10     void hello();11 }

 

【代码清单--2】真实对象角色

 1 package com.huawei.subject.Impl; 2  3 import com.huawei.subject.Subject; 4 /** 5  * 真实对象角色 6  * @author Administrator 7  * 8  */ 9 public class RealSubject implements Subject 10 {11 12     @Override13     public void rent()14     {15         System.out.println("我想要出租my building");16     }17 18     @Override19     public void hello() 20     {21         System.out.println("租客你好");22     }23 24 }

 

【代码清单--3】代理类

 1 package com.huawei.proxy; 2  3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Method; 5  6 /** 7  * 动态代理角色 8  * @author Administrator 9  *10  */11 public class DynamicProxy implements InvocationHandler 12 {13     //这个是我们要代理的真实对象14     private Object subject;15     //构造方法,给我们要代理的真实对象赋初值16     public DynamicProxy(Object obj)17     {18         this.subject = obj;19     }20     21 22     @Override23     public Object invoke(Object object, Method method, Object[] args)24             throws Throwable 25     {26         //可以在代理真实对象之前进行一些自己的操作27         System.out.println("Mrthod :"+method);28         //当代理对象调用真实对象的方法时,其会自动的跳转到代理对象的handler对象的invoke方法来进行调用29         method.invoke(subject, args);30         31         //可以在代理真实对象之后进行一些自己的操作32         33         return null;34     }35 36 }

 

【客户端】--测试类

 1 package com.huawei; 2  3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.Proxy; 5  6 import com.huawei.proxy.DynamicProxy; 7 import com.huawei.subject.Subject; 8 import com.huawei.subject.Impl.RealSubject; 9 10 public class Main {11 12     public static void main(String[] args) 13     {14         //我们要代理的真实对象15         Subject realSubject = new RealSubject();16         //我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的17         InvocationHandler handler = new DynamicProxy(realSubject);18         /**19          * 通过Proxy的newInstance方法来创建我们的代理对象20          * 第一个参数handler.getClass().getClassLoader(),我们这里使用这个21          * handler这个类的ClassLoader对象来加载我们的代理对象;22          * 第二个参数realSubject.getClass().getInterface(),我们这里为代理对象提供的接口23          * 是真实对象所实现的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了;24          * 第三个参数handler,这里讲这个代理对象关联到上方的InvocationHandler这个对象上25          */26         27         Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), 28                                                     realSubject.getClass().getInterfaces(), 29                                                     handler);30         31         System.out.println(subject.getClass().getName());32         33         subject.rent();34         subject.hello();35 36     }37 38 }

 

【运行结果】

com.sun.proxy.$Proxy0Mrthod :public abstract void com.huawei.subject.Subject.rent()我想要出租my buildingMrthod :public abstract void com.huawei.subject.Subject.hello()租客你好

 

  通过Proxy.newInstance创建的代理对象是在JVM运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行时动态生成的一个对象,

并且明明方式都是这样的形式,以$开头,proxy为重,最后一个数字表示对象的标号。

subject.rent();
subject.hello();

  这里是通过代理对象来调用实现的那种接口中的方法,这个时候程序就会跳转到由这个代理对象关联到的handler中的invoke方法去执行,而我们

的这个handler对象又接受一个RealSubject类型的参数,表示我要代理的就是这个真实对象,所以此时就会调用handler中invoke方法去执行。

 

  由结果可知,也证明了当我们通过代理对象来调用方法的时候,实际就是委托有其关联到的handler对象的invoke方法中来调用,并不是自己真实调用,而是通过代理的方法来调用的。

java动态代理模式