问题描述
这是我的第一个,也是 Spring.NET 和 AOP 的初学者.
this is my first and also I am beginner in Spring.NET and also AOP.
我想使用 Aspect for Exception Hadling 来替换、包装和修改我的自定义异常.
I would like use Aspect for Exception Hadling for replacing, wrap and modify my custom exceptions.
首先我定义了一些实体和 DAO.从 DAO 中的 Save 方法中,我将抛出我的异常.
First I defined some entity and DAO. From method Save in DAO I will throw my exception.
仅供参考:这是一个愚蠢的样本
FYI: This is silly sample
实体:
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
替换为 System.ArgumentException
.
In app.config I defined CustomerDao
object and ExceptionHandlerAdvice
object which only replace CustomerException
for System.ArgumentException
.
我不确定 ExceptionHandlerAdvice
是否是自动代理,我也不知道它是如何识别目标的.
I am not sure if ExceptionHandlerAdvice
is auto-proxy and also I don’t how it identified targets.
我相信它使用 SpEL 来定义规则,当出现异常时,它会抛出检查列表.好的,这种类型的例外在列表中,我将应用一些建议.
I believe that it uses SpEL for define rules and when there is some exception it throws check list.Ok this type of exception is in list some I will apply advice.
谁能向我解释一下这方面是如何确定目标的?例如,我只想将这个方面应用于少数对象而不是全部.
Can anybody explain to me how this aspect identified targets? For example I would like apply this aspect only for a few objects not all.
我使用参考文档第 14.3 章异常处理,但我找不到这些信息.
I use ref documentation Chapter 14.3 Exception handling but I couldnt find these information.
这是 app.config:
<?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>
我的主要问题是,如果我在 DAO 上调用 Save 方法,它会抛出 CustomerException 异常类型,此异常不会被替换.为什么?
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
的类型,而不是 ArgumentException
,
Thrown exception is type of CustomerException
not ArgumentException
,
当建议适用时,我也尝试使用 DSL 来定义规则:
Also I tried use DSL for defined rules when advice apply:
on exception (#e is T(ExceptionHandlingTutorial.CustomerException) translate new System.ArgumentException('XChange, Method Name'+ #method.Name, #e))
但仍然是抛出异常类型的 CustomerException.
But still is throw exception type of CustomerException.
感谢您的帮助.
推荐答案
Spring.NET aop 为要应用建议的对象动态创建代理.当您执行 var customerDao = (ICustomerDao)context["customerDao"];
时,Spring.NET 会返回此代理.所以如果配置正确,你不会得到一个 CustomerDao
实例,而是一个来自 Spring 的实现 ICustomerDao
接口的 aop 代理.此代理拦截对 Save(...)
的调用并应用您的异常处理建议.
Spring.NET aop dynamically creates a proxy for the objects you want to apply advice to. Spring.NET returns this proxy when you do var customerDao = (ICustomerDao)context["customerDao"];
. So when configured correctly, you don't get a CustomerDao
instance, but an aop proxy from Spring implementing the ICustomerDao
interface. This proxy intercepts the call to Save(...)
and applies your exception handling advice.
然而,你没有配置ProxyFactory
,所以你不会得到一个代理,而是在调用var customerDao = (ICustomerDao)时得到一个
.您可以在调试器中进行检查;检查 CustomerDao
实例上下文["customerDao"];customerDao
的(运行时)类型.
However, you haven't configured a ProxyFactory
, so you will not get a proxy, but a CustomerDao
instance when calling var customerDao = (ICustomerDao)context["customerDao"];
. You can check this in the debugger; inspect the (runtime) type of customerDao
.
配置代理工厂的方法有多种;我建议您使用 AdvisorAutoProxy
适用于您的情况,但您也可以使用普通的 ProxyFactoryObject
或其他 AutoProxy
.
There are several methods to configure the proxy factory; I'd advise you to use an AdvisorAutoProxy
for your case, but you can also configure it manually for each object using a plain ProxyFactoryObject
or another AutoProxy
.
使用 AdvisorAutoProxy
时,您必须将以下对象定义添加到您的配置中:
When using an AdvisorAutoProxy
, you have to add the following object definitions to your configuration:
<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" />
这篇关于Spring.NET.AOP - ExceptionHandlerAdvice 不替换自定义异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!