Spring.NET.AOP - ExceptionHandler建议不替换自定义异常

时间:2011-11-17 13:17:13

标签: exception-handling spring.net aop

这是我的第一个,也是我在Spring.NET和AOP的初学者。

我想使用Aspect for Exception Hadling来替换,包装和修改我的自定义异常。

首先我定义了一些实体和DAO。从方法保存在DAO中我将抛出异常。

仅供参考:这是愚蠢的样本

实体:

namespace ExceptionHandlingTutorial.Entities
{
    public class Customer
    {
        public long Id { get; set; }
        public string Name { get; set; }
    }
}

DAO:

namespace ExceptionHandlingTutorial.Dao
{
    public interface ICustomerDao
    {
        void Save(Customer customer);
    }

    public class CustomerDao:ICustomerDao
    {
        #region Implementation of ICustomerDao

        public void Save(Customer customer)
        {
            throw new CustomerException(
                string.Format("Customer with id {0} already exist in repository",customer.Id));
        }

        #endregion
    }
}

CustomException类定义在这里:

namespace ExceptionHandlingTutorial
{
    public class CustomerException : Exception
    {
        public CustomerException(string msg)
            : base(msg)
        {

        }
    }
}

在app.config中,我定义了CustomerDao对象和ExceptionHandlerAdvice对象,该对象仅替换CustomerException的{​​{1}}。

我不确定System.ArgumentException是否为自动代理,而且我不知道它是如何识别目标的。

我相信它使用SpEL来定义规则,当有一些异常时它会抛出检查列表。 好的,这种类型的异常在列表中,我将应用建议。

有人可以向我解释这方面是如何确定目标的吗?例如,我想将此方面仅应用于少数几个对象。

我使用ref文档第14.3章异常处理,但我找不到这些信息。

这是app.config:

ExceptionHandlerAdvice

我的主要问题是,如果我在DAO上调用Save方法,则抛出异常类型的CustomerException,不会替换此异常。为什么?

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
      <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core"/>
    </sectionGroup>
  </configSections>

  <spring>

    <context>
      <resource uri="config://spring/objects"/>
    </context>

    <objects xmlns="http://www.springframework.net">

      <object id="customerDao" 
              type="ExceptionHandlingTutorial.Dao.CustomerDao, ExceptionHandlingTutorial"/>

      <object id="exceptionHandlerAdvice" 
              type="Spring.Aspects.Exceptions.ExceptionHandlerAdvice, Spring.Aop">

        <property name="ExceptionHandlers">
          <list>
            <value>on exception name CustomerException replace System.ArgumentException 'Something'</value>
          </list>
        </property>

      </object>

    </objects>

  </spring>
</configuration>

引发异常的类型为try { var context = ContextRegistry.GetContext(); var customerDao = (ICustomerDao)context["customerDao"]; customerDao.Save(new Customer { Id = 1, Name = "Customer_1" }); } catch (Exception ex) { Console.WriteLine(string.Format("Exception type: {0}\nException message: {1}\n", ex.GetType(),ex.Message)); } 而不是CustomerException

当建议适用时,我也尝试使用DSL来定义规则:

ArgumentException

但仍然是抛出异常类型的CustomerException。

谢谢你的帮助。

1 个答案:

答案 0 :(得分:2)

Spring.NET aop为您要应用建议的对象动态创建代理。执行var customerDao = (ICustomerDao)context["customerDao"];时,Spring.NET会返回此代理。所以如果配置正确,你就不会得到一个CustomerDao实例,而是一个实现ICustomerDao接口的Spring的aop代理。此代理拦截对Save(...)的调用并应用您的异常处理建议。

但是,您尚未配置ProxyFactory,因此在调用CustomerDao时,您将无法获得代理,而是var customerDao = (ICustomerDao)context["customerDao"];实例。你可以在调试器中检查这个;检查customerDao的(运行时)类型。

有几种方法可以配置代理工厂;我建议您使用AdvisorAutoProxy作为案例,但您也可以使用普通ProxyFactoryObject或其他AutoProxy为每个对象手动配置。

使用AdvisorAutoProxy时,必须将以下对象定义添加到配置中:

<object id="ExceptionAdvisorForSaveMethods" 
        type="Spring.Aop.Support.RegularExpressionMethodPointcutAdvisor, Spring.Aop">
  <property name="advice" ref="exceptionHandlerAdvice"/>
  <property name="patterns">
    <list>
      <value>.*Save.*</value>
    </list>
  </property>
</object>

<object id="ProxyCreator" 
        type="Spring.Aop.Framework.AutoProxy.DefaultAdvisorAutoProxyCreator, Spring.Aop" />