设计模式之Dynamic Proxy-动态代理
动态代理(Dynamic Proxy)是JDK5 提供的一种新特性。其特点在于在程序的运行时刻动态的创建出代理类及其对象,而不像我们使用静态代理时必须在编译之前定义好代理类。在运行时刻,框架帮我们动态的创建出一个实现了多个接口的代理类,每个代理类的对象都会和一个InvocationHandler接口的实现类相关联。当我们调用了代理对象所代理的接口中的方法的时候,这个调用的信息会被传递给InvocationHandler的invoke方法。在 invoke方法的参数中可以获取到代理对象、方法对应的Method对象和调用的实际参数(内部是通过反射来实现的)。 invoke方法的返回值被返回给使用者,至于返回什么值可以由自己来定义,这种做法实际上相当于对方法调用进行了AOP拦截。
创建动态代理的步骤如下:
1. 创建一个实现接口InvocationHandler的类,它必须实现invoke方法。
2. 创建被代理类以及接口
3. 通过Proxy的静态方法newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)创建一个代理
4. 通过代理来调用方法(此代理实现了被代理类的接口)
写了个示例代码:
/** * DynamicSubject.java * dynamicproxy * * Function: 动态代理类, java.lang.reflect.Proxy 是运行时生成的Class,在生成它的时候你必须传递 * 一组Interfaces给它(多个接口),然后返回的对象就实现了这些接口,这个Proxy就是一个纯粹的Porxy, * 所以我们必须提供一个InvocationHandler,由它来接替 * * ver date author * ────────────────────────────────── * 2011-6-12 Leon * * Copyright (c) 2011, TNT All Rights Reserved. */ package dynamicproxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * ClassName:DynamicSubject * Function: TODO ADD FUNCTION * 创建动态代理的步骤如下: * 1. 创建一个实现接口InvocationHandler的类,它必须实现invoke方法。 * 2. 创建被代理类以及接口 * 3. 通过Proxy的静态方法newProxyInstance(ClassLoader loader, * Class[] interfaces, InvocationHandler h)创建一个代理 * 4. 通过代理来调用方法(此代理实现了被代理类的接口) * * * Reason: TODO ADD REASON * * @author Leon * @version * @since Ver 1.1 * @Date 2011-6-12 */ public class DynamicProxy implements InvocationHandler { private Object sub ; public Object getSub() { return sub; } public void setSub(Object sub) { this.sub = sub; } public DynamicProxy(Object obj){ this.sub=obj; } //proxy是框架动态生成的代理类 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub Object result = null ; System.out.println("before calling: " + method); //此处是真正被代理的对象 result=method.invoke(sub, args); System.out.println("after calling ..."); return result; } public static void main(String... args){ RealSubject realSubject = new RealSubject(); DynamicProxy dynamicProxy = new DynamicProxy(realSubject); // InvocationHandler invocationHandler = dynamicProxy; //动态生成一个代理对象,返回的对象既不是RealSubject实例也不是DynamicPorxy的实例,而是动态生成 //的一个实例 $prxoy0,它实现了realSubject.getClass().getInterfaces()这些接口 ISubject subject=(ISubject)Proxy.newProxyInstance(dynamicProxy.getClass().getClassLoader(), realSubject.getClass().getInterfaces(),dynamicProxy); //当调用这一句的时候,$proxy0就会调用上面传入的invocationHandler的invoke方法,所以上面的方法要传入invocationHandler。 System.out.println("--------------------------Porxy realSubject1 ------------------------------------"); subject.request(); String result=subject.test(); System.out.println("return by test method :" + result); System.out.println("--------------------------Proxy realSubject2--------------------------------------"); dynamicProxy.setSub(new RealSubject2()); subject.request(); System.out.println("proxy generate by system is :"+subject.getClass()); } } interface ISubject { public void request(); public String test(); } class RealSubject implements ISubject { @Override public void request() { // TODO Auto-generated method stub System.out.println("From real subject...request method...."); } @Override public String test() { // TODO Auto-generated method stub String str ="From real subject.....test method....."; return str ; } } class RealSubject2 implements ISubject { @Override public void request() { // TODO Auto-generated method stub System.out.println("From real subject2...request method...."); } @Override public String test() { // TODO Auto-generated method stub System.out.println("From real subject2 .....test method....."); return null ; } }