走在架構師的大道上 Jack.Wang's home

          Java, C++, linux c, C#.net 技術,軟件架構,領域建模,IT 項目管理 Dict.CN 在線詞典, 英語學習, 在線翻譯

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            195 Posts :: 3 Stories :: 728 Comments :: 0 Trackbacks

          公告

          重構
          新浪博客:新浪 blog
          MSN: wbjeasygo@163.com
          Email:  wbjeasygo@163.com
          QQ 精英群: 47763528 
          空間QQ空間

          淘寶店:新開淘寶書店
          致謝:
           感謝雷老師幾年的指導
           感謝導師在學業上的關懷,
           感謝老婆的支持,
           感謝我的同學和同事,
           在我成長的路上有你

          留言簿(26)

          我參與的團隊

          隨筆分類(232)

          隨筆檔案(190)

          我的鄰居們

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          通常我們對于異常的處理方式都是大同小異的,要么直接捕獲并處理,要么讓它拋向上一層,要么就是記錄到日志里,或者發郵件提供管理員,但這樣下來一個項目中便會到處充斥著 try/catch ,并且 catch 中的代碼基本類似,于是我們聞到的其中難聞的壞味道。

                   本文將介紹如何通過 Spring.Net 的 AOP 特性實現異常的統一處理,如果我們需要在異常發生時做一些操作的話我們就必須實現 Spring.Aop.IThrowsAdvice,該接口沒有任何實現方法,是一個空接口,它僅僅做為一個標記接口而存在,但實現了 IThrowsAdvice 接口的類必須定義至少一個 AfterThrowing 方法,方法的簽名如下:

                   AfterThrowing([MethodInfo method, Object[] args, Object target], Exception subclass);

                   其中中括號括起來的前三個參數是可選的,返回值可以是任意數據類型。Spring.Aop.Framework.Adapter.ThrowsAdviceInterceptor 類實現對實現了 Spring.Aop.IThrowsAdvice 派生類中的方法依賴注入,其中的 ThrowsAdviceInterceptor() 方法檢查 Spring.Aop.IThrowsAdvice 的派生類是否定義了至少一個異常處理方法,如果沒有則拋出 ArgumentException 異常,MapAllExceptionHandlingMethods() 方法則在定義好的重載方法中查找出異常類型與最后一個參數所定義的類型中最接近的方法,而且我們不應該在其中實現了兩個相同異常類型的方法,即使他們的參數數目不同,否則也將拋出 ArgumentException 異常。

                   [下面引用自《Spring 技術手冊》第4章 P94 頁中的一段話]
                   注意到當異常發生時, Throw Advice 的任務只是執行對應的方法,您并不能在 Throw Advice 中將異常處理掉,在 Throw Advice 執行完畢后,原告的異常仍將傳播至應用程序之中, Throw Advice 并不介入應用程序的異常處理,異常處理仍舊是應用程序本身所要負責的,如果想要在 Throw Advice 處理時中止應用程序的處理流程,作法是拋出其它的異常。

                   接下來看個 Throws Advice 的實際例子,首先定義 IHello 接口:

          using System;

          namespace TestThrowAdvice
          {
              
          public interface IHello
              
          {
                  
          void Hello(string name);
              }

          }

                   接著定義一個 HelloSpeaker 類來實現 IHello 接口,并在 Hello() 方法中模擬程序發生錯誤時的異常拋出:

          using System;

          namespace TestThrowAdvice
          {
              
          public class HelloSpeaker : IHello
              
          {
                  
          public void Hello(string name)
                  
          {
                      Console.WriteLine(
          "Hello, " + name);
                      
          //抱歉! 程序錯誤! 發生異常 XD
                      throw new Exception("發生異常");
                  }

              }

          }




                   如果您需要在應用程序拋出異常時,介入 Throw Advice 提供一些服務,例如記錄一些異常信息,則可以實現 Spring.Aop.IThrowsAdvice 接口,在這個例子中我使用了 log4net 組件來實現日志的記錄:

          using System;
          using Spring.Aop;
          using log4net;
          using log4net.Core;
          using System.Reflection;

          [assembly: log4net.Config.XmlConfigurator(Watch 
          = true)]
          namespace TestThrowAdvice
          {
              
          public class SomeThrowAdvice : IThrowsAdvice
              
          {
                  
          private ILog logger;

                  
          public SomeThrowAdvice()
                  
          {
                      logger 
          = LogManager.GetLogger(this.GetType());
                  }


                  
          public void AfterThrowing(MethodInfo method, Object[] args, Object target, Exception exception)
                  
          {
                      
          // 記錄異常
                      logger.Info("記錄異常", exception);
                  }

              }

          }

           
                  接著在配置文件(我這里使用了獨立配置文件)中寫下以下的定義,讓 Throw Advice 在異常發生時提供記錄服務:

          <?xml version="1.0" encoding="utf-8"?>
          <objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                   xsi:schemaLocation
          ="http://www.springframework.net 
                   http://www.springframework.net/xsd/spring-objects.xsd"
          >

            
          <object id="SomeThrowAdvice" type="TestThrowAdvice.SomeThrowAdvice, TestThrowAdvice" />
            
          <object id="HelloSpeaker" type="TestThrowAdvice.HelloSpeaker, TestThrowAdvice" />

            
          <object id="HelloProxy" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop" >
              
          <property name="ProxyInterfaces">
                
          <list>
                  
          <value>TestThrowAdvice.IHello,TestThrowAdvice</value>
                
          </list>
              
          </property>
              
          <property name="Target">
                
          <ref object="HelloSpeaker" />
              
          </property>
              
          <property name="InterceptorNames">
                
          <list>
                  
          <value>SomeThrowAdvice</value>
                
          </list>
              
          </property>
            
          </object>
            
          </objects>

           
                  最后剩下我們的程序入口 Main() 函數了:

          using System;
          using Spring.Context;
          using Spring.Context.Support;

          namespace TestThrowAdvice
          {
              
          public class Program
              
          {
                  
          static void Main(string[] args)
                  
          {
                      log4net.Config.XmlConfigurator.Configure(); 
                      IApplicationContext context 
          = new XmlApplicationContext(@"../../SpringNet.xml");
                      IHello helloProxy 
          = (IHello)context.GetObject("HelloProxy");

                      
          try
                      
          {
                          helloProxy.Hello(
          "Justin");
                      }

                      
          catch (Exception ex)
                      
          {
                          
          // 應用程序的異常處理
                          Console.WriteLine(ex.Message);
                      }

                  }

              }

          }

           
                  程序執行結果輸出:
                   Hello, Justin
                   發生異常...

                   日志記錄中的結果:
                   2006-10-30 20:59:03,125 [4020] INFO  TestThrowAdvice.SomeThrowAdvice - 記錄異常
                   System.Exception: 發生異常...
                      在 TestThrowAdvice.HelloSpeaker.Hello(String name) 位置 E:\..\..\SpringNetDemo\TestThrowAdvice\HelloSpeaker.cs:行號 14
                      在 Spring.Objects.ObjectUtils.InvokeMethod(MethodInfo method, Object instance, Object[] arguments) 位置     c:\projects\daily\Spring.Net\src\Spring\Spring.Core\Objects\ObjectUtils.cs:行號 489
             在 Spring.Aop.Framework.ReflectiveMethodInvocation.InvokeJoinpoint() 。。。。。





          本博客為學習交流用,凡未注明引用的均為本人作品,轉載請注明出處,如有版權問題請及時通知。由于博客時間倉促,錯誤之處敬請諒解,有任何意見可給我留言,愿共同學習進步。
          posted on 2008-04-20 22:07 Jack.Wang 閱讀(6577) 評論(0)  編輯  收藏 所屬分類: 開發技術
          主站蜘蛛池模板: 昌都县| 黑河市| 兴宁市| 南和县| 楚雄市| 富川| 富顺县| 永新县| 金川县| 建瓯市| 西吉县| 曲麻莱县| 龙泉市| 龙游县| 荣成市| 普洱| 乳源| 凤翔县| 临西县| 五常市| 鄂托克前旗| 庆元县| 松江区| 林口县| 兴化市| 桃园市| 理塘县| 宜城市| 河南省| 家居| 呈贡县| 赤壁市| 贺兰县| 青浦区| 兴仁县| 驻马店市| 温宿县| 焦作市| 囊谦县| 沿河| 肇源县|