首页 > 代码库 > 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动态代理模式