代理模式()
動態代理介紹
動態代理是指在運行時動態生成代理類即代理類的字節碼將在運行時生成並載入當前的ClassLoader與靜態代理類相比動態類有諸多好處首先不需要為真實主題寫一個形式上完全一樣的封裝類假如主題接口中的方法很多為每一個接口寫一個代理方法也是非常煩人的事如果接口有變動則真實主題和代理類都要修改不利於系統維護其次使用一些動態代理的生成方法甚至可以在運行時指定代理類的執行邏輯從而大大提升系統的靈活性
注意動態代理使用字節碼動態生成加載技術在運行時生成並加載類
生成動態代理類的方法很多如JDK自帶的動態代理CGLIBJavassist或者ASM庫JDK的動態代理使用簡單它內置在JDK中因此不需要引入第三方Jar包但相對功能比較弱CGLIB和Javassist都是高級的字節碼生成庫總體性能比JDK自帶的動態代理好而且功能十分強大ASM是低級的字節碼生成工具使用ASM已經近乎於在使用Java bytecode編程對開發人員要求最高當然也是性能最好的一種動態代理生成工具但ASM的使用實在過於繁瑣而且性能也沒有數量級的提升與CGLIB等高級字節碼生成工具相比ASM程序的可維護性也較差如果不是在對性能有苛刻要求的場合筆者還是推薦CGLIB或者Javassist
動態代理實現
以上例中的DBQueryProxy為例使用動態代理生成動態類替代上例中的DBQueryProxy首先使用JDK的動態代理生成代理對象JDK的動態代理需要實現一個處理方法調用的Handler用於實現代理方法的內部邏輯
public class JdkDbQeuryHandler implements InvocationHandler {
IDBQuery real=null; //主題接口
@Override
public Object invoke(Object proxy Method method Object[] args)
throws Throwable {
if(real==null)
real=new DBQuery() //如果是第一次調用則生成真實對象
return realrequest() //使用真實主題完成實際的操作
}
}
以上代碼實現了一個Handler可以看到它的內部邏輯和DBQueryProxy是類似的在調用真實主題的方法前先嘗試生成真實主題對象接著需要使用這個Handler生成動態代理對象
public static IDBQuery createJdkProxy(){
IDBQuery jdkProxy = (IDBQuery) ProxynewProxyInstance(
ClassLoadergetSystemClassLoader()
new Class[] { IDBQueryclass }
new JdkDbQeuryHandler()) //指定Handler
return jdkProxy;
}
以上代碼生成一個實現了IDBQuery接口的代理類代理類的內部邏輯由JdkDbQeuryHandler決定生成代理類後由newProxyInstance()方法返回該代理類的一個實例至此一個完整的JDK動態代理就完成了
CGLIB和Javassist的動態代理的使用和JDK的動態代理非常類似下面嘗試使用CGLIB生成動態代理CGLIB也需要實現一個處理代理邏輯的切入類
public class CglibDbQueryInterceptor implements MethodInterceptor {
IDBQuery real=null;
@Override
public Object intercept(Object arg Method arg Object[] arg
MethodProxy arg) throws Throwable {
if(real==null) //代理類的內部邏輯
//和前文中的一樣
real=new DBQuery()
return realrequest()
}
}
返回目錄Java程序性能優化讓你的Java程序更快更穩定
編輯推薦
Java程序設計培訓視頻教程
JEE高級框架實戰培訓視頻教程
JME移動開發實戰教學視頻
Visual C++音頻/視頻技術開發與實戰
Oracle索引技術
ORACLEG數據庫開發優化指南
From:http://tw.wingwit.com/Article/program/Java/gj/201311/27832.html