利用AOP重构代码
????? AOP是什么?
??? AOP是OOP的延續(xù),Aspect Oriented Programming的縮寫,即面向方面編程。AOP是GoF設計模式的延續(xù),設計模式追求的是調(diào)用者和被調(diào)用者之間的解耦,AOP也是這種目標的一 種實現(xiàn)。
??????案例:在應用程序中,我們經(jīng)常會對某一段程序做異常處理,或者是把一個方法的調(diào)用所消耗的時間體現(xiàn)在日志中,如果我們對每個方法都寫具體的實現(xiàn),我想并不是一件輕松的事情。對于異常處理來講,其實我們平常編程很少去捕獲具體的異常,當然特殊程序除外,例如客戶端捕獲WCF異常時最好捕獲CommunicationException,TimeoutException,Exception。否則一般都會直接捕獲Exception,因為很多異常往往是意料之外的異常。對于記錄方法調(diào)用時間問題,我想也非常麻煩,下面例子簡單的展示了記錄時間:當你需要對多個方法都需要記錄時間時,這些代碼往往讓人感覺有重構(gòu)的必要。
???
Stopwatch?sw?=?new?Stopwatch();???sw.Start();
???//方法執(zhí)行.....
???sw.Stop();
???WebLog.SquareLog.CommonLogger.Error("取積分廣場首頁酒店數(shù)據(jù)用時:"+sw.ElapsedMilliseconds?.ToString?()+"毫秒");
?
??? ? 上面的記錄方法調(diào)用用時,如果抽象出來,其實有下列特性:
????? 1:不是具體訪問類的首要或主要功能,訪問類主要功能是業(yè)務邏輯處理。
????? 2:具體訪問類的主要功能可以獨立、區(qū)分開來的。
????? 3:是這個系統(tǒng)的一個縱向切面,涉及多個類、多個類的方法。示意圖如下:
?
?????
?
????? aspect:? 新的程序結(jié)構(gòu)關注系統(tǒng)的縱向切面,例如這里的異常處理以及方法調(diào)用時間記錄,這個新的程序結(jié)構(gòu)就是aspect(方面),方面(aspect)應該有以下職責:提供一些必備的功能,對被訪問對象實現(xiàn)特有功能,以保證所以方法在被執(zhí)行時都能正常的執(zhí)行異常處理或者是其它的功能。
???? ?AOP應用范圍
????? 1:Authentication 權(quán)限
???? ?2:Error handling 錯誤處理
????? 3:logging, tracing, profiling and monitoring 記錄跟蹤 優(yōu)化 校準
??? ??......
???? AOP具體實現(xiàn):主要是利用泛型委托來實現(xiàn)AOP思想。但泛型委托有一個局限就是最多支持四個參數(shù),當你的方法超過四個時就不太好應用AOP重構(gòu)了。我最近分析了有以下三個地方我們可以對代碼進行優(yōu)化:
???? 第一:普通方法異常處理:ErrorHandler類,實現(xiàn)類參考第二或者是第三。
??????????? 客戶端調(diào)用:
?????????
???????????list?=?ErrorWCFHandler?.Invoke<ISearchHotelForSquare,?List<HotelGenericInfo>>(cli,?proxy?=>?proxy.GetHotelGenericListForSquare(requestInfo).ToList()?);?
?
???? 第二:客戶端調(diào)用WCF的異常處理:ErrorWCFHandler。
??????????? 代碼:
代碼 public??class?ErrorWCFHandler????{
???????public?static?void?Invoke<TContract>(TContract?proxy,?Action<TContract>?action,?string?MethodElapsedTimeText,?string?MethodErrorText)
????????{
????????????Stopwatch?sw?=?new?Stopwatch();
????????????sw.Start();
????????????try
????????????{
????????????????action(proxy);
????????????????(proxy?as?ICommunicationObject).Close();
????????????}
????????????catch?(CommunicationException?ex)
????????????{
????????????????(proxy?as?ICommunicationObject).Abort();
????????????????//Handle?Exception?????????????
????????????????//throw;
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????catch?(TimeoutException?ex)
????????????{
????????????????(proxy?as?ICommunicationObject).Abort();
????????????????//Handle?Exception?????????
????????????????//throw;
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????//Handle?Exception????????
????????????????//(proxy?as?ICommunicationObject).Close();??????
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????sw.Stop();
????????????WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText?+?sw.ElapsedMilliseconds.ToString()?+?"毫秒");
????????}
???????public?static?TReturn?Invoke<TContract,?TReturn>(TContract?proxy,?Func<TContract,?TReturn>?func,?string?MethodElapsedTimeText,?string?MethodErrorText)
????????{
????????????Stopwatch?sw?=?new?Stopwatch();
????????????sw.Start();
????????????TReturn?returnValue?=?default(TReturn);
????????????try
????????????{
????????????????returnValue?=?func(proxy);
????????????}
????????????catch?(CommunicationException?ex)
????????????{
????????????????(proxy?as?ICommunicationObject).Abort();
????????????????//Handle?Exception?????
????????????????//throw;
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????catch?(TimeoutException?ex)
????????????{
????????????????(proxy?as?ICommunicationObject).Abort();
????????????????//Handle?Exception???????
????????????????//throw;
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????//Handle?Exception??
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????sw.Stop();
????????????WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText?+?sw.ElapsedMilliseconds.ToString()?+?"毫秒");
????????????return?returnValue;
????????}
????}
?
????????? 客戶端調(diào)用:
??????????
???????????string?ErrorMethodText="取積分廣場首頁酒店數(shù)據(jù)異常:";
???????????list?=?ErrorWCFHandler?.Invoke<ISearchHotelForSquare,?List<HotelGenericInfo>>(cli,?proxy?=>?proxy.GetHotelGenericListForSquare(requestInfo).ToList
(),ComputationTimeText?,ErrorMethodText?);??
?
?? ?? 第三:記錄方法調(diào)用時間,這中間也增加了異常處理:ErrorAndComputationTimeHandler
??????????? 代碼:
????{
????????public?static?void?Invoke<TContract>(TContract?proxy,?Action<TContract>?action,?string?MethodElapsedTimeText,string?MethodErrorText)
????????{
????????????Stopwatch?sw?=?new?Stopwatch();
????????????sw.Start();
????????????try
????????????{
????????????????action(proxy);
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????//Handle?Exception???
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????sw.Stop();
????????????WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText??+?sw.ElapsedMilliseconds.ToString()?+?"毫秒");
????????}
????????public?static?void?Invoke<TContract,?TContract2>(TContract?proxy,?TContract2?proxy2,?Action<TContract,?TContract2>?action,?string?MethodElapsedTimeText,string?MethodErrorText)
????????{
????????????Stopwatch?sw?=?new?Stopwatch();
????????????sw.Start();
????????????try
????????????{
????????????????action(proxy,?proxy2);
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????//Handle?Exception???
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????sw.Stop();
????????????WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText??+?sw.ElapsedMilliseconds.ToString()?+?"毫秒");
????????}
????????public?static?void?Invoke<TContract,?TContract2,?TContract3>(TContract?proxy,?TContract2?proxy2,?TContract3?proxy3,?Action<TContract,?TContract2,?TContract3>?action,?string?MethodElapsedTimeText,string?MethodErrorText)
????????{
????????????Stopwatch?sw?=?new?Stopwatch();
????????????sw.Start();
????????????try
????????????{
????????????????action(proxy,?proxy2,?proxy3);
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????//Handle?Exception???
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????sw.Stop();
????????????WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText??+?sw.ElapsedMilliseconds.ToString()?+?"毫秒");
????????}
????????public?static?void?Invoke<TContract,?TContract2,?TContract3,?TContract4>(TContract?proxy,?TContract2?proxy2,?TContract3?proxy3,?TContract4?proxy4,?Action<TContract,?TContract2,?TContract3,?TContract4>?action,??string?MethodElapsedTimeText,string?MethodErrorText)
????????{
????????????Stopwatch?sw?=?new?Stopwatch();
????????????sw.Start();
????????????try
????????????{
????????????????action(proxy,?proxy2,?proxy3,?proxy4);
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????//Handle?Exception???
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????sw.Stop();
????????????WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText??+?sw.ElapsedMilliseconds.ToString()?+?"毫秒");
????????}
????????public?static?TReturn?Invoke<TContract,?TReturn>(TContract?proxy,?Func<TContract,?TReturn>?func,??string?MethodElapsedTimeText,string?MethodErrorText)
????????{
????????????Stopwatch?sw?=?new?Stopwatch();
????????????sw.Start();
????????????TReturn?returnValue?=?default(TReturn);
????????????try
????????????{
????????????????returnValue?=?func(proxy);
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????//Handle?Exception???
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????sw.Stop();
????????????WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText??+?sw.ElapsedMilliseconds.ToString()?+?"毫秒");
????????????return?returnValue;
????????}
????????public?static?TReturn?Invoke<TContract,?TContract2,?TReturn>(TContract?proxy,?TContract2?proxy2,?Func<TContract,?TContract2,?TReturn>?func,??string?MethodElapsedTimeText,string?MethodErrorText)
????????{
????????????Stopwatch?sw?=?new?Stopwatch();
????????????sw.Start();
????????????TReturn?returnValue?=?default(TReturn);
????????????try
????????????{
????????????????returnValue?=?func(proxy,?proxy2);
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????//Handle?Exception???
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????sw.Stop();
????????????WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText??+?sw.ElapsedMilliseconds.ToString()?+?"毫秒");
????????????return?returnValue;
????????}
????????public?static?TReturn?Invoke<TContract,?TContract2,?TContract3,?TReturn>(TContract?proxy,?TContract2?proxy2,?TContract3?proxy3,?Func<TContract,?TContract2,?TContract3,?TReturn>?func,??string?MethodElapsedTimeText,string?MethodErrorText)
????????{
????????????Stopwatch?sw?=?new?Stopwatch();
????????????sw.Start();
????????????TReturn?returnValue?=?default(TReturn);
????????????try
????????????{
????????????????returnValue?=?func(proxy,?proxy2,?proxy3);
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????//Handle?Exception???
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????sw.Stop();
????????????WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText??+?sw.ElapsedMilliseconds.ToString()?+?"毫秒");
????????????return?returnValue;
????????}
????????public?static?TReturn?Invoke<TContract,?TContract2,?TContract3,?TContract4,?TReturn>(TContract?proxy,?TContract2?proxy2,?TContract3?proxy3,?TContract4?proxy4,?Func<TContract,?TContract2,?TContract3,?TContract4,?TReturn>?func,??string?MethodElapsedTimeText,string?MethodErrorText)
????????{
????????????Stopwatch?sw?=?new?Stopwatch();
????????????sw.Start();
????????????TReturn?returnValue?=?default(TReturn);
????????????try
????????????{
????????????????returnValue?=?func(proxy,?proxy2,?proxy3,?proxy4);
????????????}
????????????catch?(Exception?ex)
????????????{
????????????????//Handle?Exception???
????????????????WebLog.SquareLog.CommonLogger.Error(MethodErrorText?+?ex.ToString());
????????????}
????????????sw.Stop();
????????????WebLog.SquareLog.CommonLogger.Error(MethodElapsedTimeText??+?sw.ElapsedMilliseconds.ToString()?+?"毫秒");
????????????return?returnValue;
????????}
????}
?
??????????? 客戶端調(diào)用:?????
代碼 string?ComputationTimeText?=?"取酒店是否在積分廣場首頁推薦數(shù)據(jù)耗時:";????????????string?ErrorMethodText?=?"取酒店是否在積分廣場首頁推薦數(shù)據(jù)異常:";
????????????string?conn?=?WebConfig.DaoConfig.MisMasterDBReadConnectionString;
????????????HotelRecommendInfo?=?ErrorAndComputationTimeHandler.Invoke<HotelRequestInfo,?string,?List<HotelGenericInfo>>(requestInfo,?conn,?SearchRecommendHotelData,?ComputationTimeText,?ErrorMethodText);
????
?????? AOP的優(yōu)勢:
1:上述應用范例在沒有使用AOP情況下,也能解決,但是,AOP可以讓我們從一個更高的抽象概念來理解軟件系統(tǒng)。可以這么說:因為使用AOP結(jié)構(gòu),對于一個大型復雜系統(tǒng)來說可以簡化不少代碼。
2:并不是所有的人都需要關心AOP,使得其它開發(fā)人員有更多精力去關注自己的業(yè)務邏輯。
?
作者:姜敏
出處:http://www.cnblogs.com/aspnet2008/?
轉(zhuǎn)載于:https://www.cnblogs.com/ASPNET2008/archive/2010/04/18/1714528.html
總結(jié)
- 上一篇: TreeView递归系统目录
- 下一篇: web.config中httpRunTi