設(shè)計(jì)模式之Dynamic Proxy-動(dòng)態(tài)代理
動(dòng)態(tài)代理(Dynamic Proxy)是JDK5 提供的一種新特性。其特點(diǎn)在于在程序的運(yùn)行時(shí)刻動(dòng)態(tài)的創(chuàng)建出代理類(lèi)及其對(duì)象,而不像我們使用靜態(tài)代理時(shí)必須在編譯之前定義好代理類(lèi)。在運(yùn)行時(shí)刻,框架幫我們動(dòng)態(tài)的創(chuàng)建出一個(gè)實(shí)現(xiàn)了多個(gè)接口的代理類(lèi),每個(gè)代理類(lèi)的對(duì)象都會(huì)和一個(gè)InvocationHandler接口的實(shí)現(xiàn)類(lèi)相關(guān)聯(lián)。當(dāng)我們調(diào)用了代理對(duì)象所代理的接口中的方法的時(shí)候,這個(gè)調(diào)用的信息會(huì)被傳遞給InvocationHandler的invoke方法。在 invoke方法的參數(shù)中可以獲取到代理對(duì)象、方法對(duì)應(yīng)的Method對(duì)象和調(diào)用的實(shí)際參數(shù)(內(nèi)部是通過(guò)反射來(lái)實(shí)現(xiàn)的)。 invoke方法的返回值被返回給使用者,至于返回什么值可以由自己來(lái)定義,這種做法實(shí)際上相當(dāng)于對(duì)方法調(diào)用進(jìn)行了AOP攔截。
創(chuàng)建動(dòng)態(tài)代理的步驟如下:
1. 創(chuàng)建一個(gè)實(shí)現(xiàn)接口InvocationHandler的類(lèi),它必須實(shí)現(xiàn)invoke方法。
2. 創(chuàng)建被代理類(lèi)以及接口
3. 通過(guò)Proxy的靜態(tài)方法newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)創(chuàng)建一個(gè)代理
4. 通過(guò)代理來(lái)調(diào)用方法(此代理實(shí)現(xiàn)了被代理類(lèi)的接口)
寫(xiě)了個(gè)示例代碼:
/** * DynamicSubject.java * dynamicproxy * * Function: 動(dòng)態(tài)代理類(lèi), java.lang.reflect.Proxy 是運(yùn)行時(shí)生成的Class,在生成它的時(shí)候你必須傳遞 * 一組Interfaces給它(多個(gè)接口),然后返回的對(duì)象就實(shí)現(xiàn)了這些接口,這個(gè)Proxy就是一個(gè)純粹的Porxy, * 所以我們必須提供一個(gè)InvocationHandler,由它來(lái)接替 * * 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 * 創(chuàng)建動(dòng)態(tài)代理的步驟如下: * 1. 創(chuàng)建一個(gè)實(shí)現(xiàn)接口InvocationHandler的類(lèi),它必須實(shí)現(xiàn)invoke方法。 * 2. 創(chuàng)建被代理類(lèi)以及接口 * 3. 通過(guò)Proxy的靜態(tài)方法newProxyInstance(ClassLoader loader, * Class[] interfaces, InvocationHandler h)創(chuàng)建一個(gè)代理 * 4. 通過(guò)代理來(lái)調(diào)用方法(此代理實(shí)現(xiàn)了被代理類(lèi)的接口) * * * 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是框架動(dòng)態(tài)生成的代理類(lèi) @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); //此處是真正被代理的對(duì)象 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; //動(dòng)態(tài)生成一個(gè)代理對(duì)象,返回的對(duì)象既不是RealSubject實(shí)例也不是DynamicPorxy的實(shí)例,而是動(dòng)態(tài)生成 //的一個(gè)實(shí)例 $prxoy0,它實(shí)現(xiàn)了realSubject.getClass().getInterfaces()這些接口 ISubject subject=(ISubject)Proxy.newProxyInstance(dynamicProxy.getClass().getClassLoader(), realSubject.getClass().getInterfaces(),dynamicProxy); //當(dāng)調(diào)用這一句的時(shí)候,$proxy0就會(huì)調(diào)用上面?zhèn)魅氲膇nvocationHandler的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 ; } }