这是我的第一个,也是我在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。
谢谢你的帮助。
答案 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" />