我开始学习Spring.NET框架,我对代理行为,自动代理和异常处理非常困惑。
例如我定义了简单的业务对象,从这个对象中我将抛出自定义异常。
namespace Aspect.Managers
{
public interface IDbCustomerManager
{
Customer GetCustomerById(long id);
}
public class DbCustomerManager:IDbCustomerManager
{
public Customer GetCustomerById(long id)
{
throw new DbException(string.Format("Problem load customer with Id: {0}",id));
}
}
}
其次我定义了处理异常的建议。
public class LogExThrowsAdvice:IThrowsAdvice
{
public void AfterThrowing(MethodInfo method, Object[] args,
Object target, DbException exception)
{
Console.WriteLine(exception.Message);
}
}
最后,我加入了代理业务对象和建议。
在app.confing中
建议:
<object id="theLogExThrowsAdvice"
type="Aspect.LogExThrowsAdvice, Log4NetInSpringNet"/>
自动代理
<object id="theProxyCreator"
type="Spring.Aop.Framework.AutoProxy.TypeNameAutoProxyCreator, Spring.Aop">
<property name="TypeNames" value="Aspect.Managers.DbCustomerManager*"/>
<property name="InterceptorNames">
<list>
<value>theLogExThrowsAdvice</value>
</list>
</property>
</object>
测试一下:
var springContext = ContextRegistry.GetContext();
var dbMgr = (IDbCustomerManager)springContext["theDbCustomerManager"];
dbMgr.GetCustomerById(1);
异常被抛出,来自LogExThrowsAdvice的AfterThrowing方法未调用。
我尝试更改类型为BeforeAdvice的建议类型。
public class DbAccessAdvice:IMethodBeforeAdvice
{
#region Implementation of IMethodBeforeAdvice
public void Before(MethodInfo method, object[] args, object target)
{
Console.WriteLine("You try access to DB");
}
#endregion
}
并在app.config中:
<object id="theDbAccessAdvice"
type="Aspect.DbAccessAdvice, Log4NetInSpringNet"/>
<object id="theProxyCreator"
type="Spring.Aop.Framework.AutoProxy.TypeNameAutoProxyCreator, Spring.Aop">
<property name="TypeNames" value="Aspect.Managers.DbCustomerManager*"/>
<property name="InterceptorNames">
<list>
<value>theDbAccessAdvice</value>
<value>theLogExThrowsAdvice</value>
</list>
</property>
</object>
BeforeAdvice是火,但是ThrowsAdvice没有。为什么呢?
我尝试更改代理对象工厂的自动代理,并尝试代理接口IDbCustomerManager。
<object id="theProxy"
type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop">
<property name="ProxyInterfaces" value="Aspect.Managers.IDbCustomerManager"/>
<property name="Target">
<object type="Aspect.Managers.DbCustomerManager">
</object>
</property>
<property name="InterceptorNames">
<list>
<value>theDbAccessAdvice</value>
<value>theLogAdvice</value>
</list>
</property>
</object>
var springContext = ContextRegistry.GetContext();
var dbMgr = (IDbCustomerManager)springContext["theProxy"];
dbMgr.GetCustomerById(1);
在提出建议之前,建议不是吗?为什么?只抛出异常。
对我而言,它是如何真正起作用的。
我尝试使用Advisors而不是建议:
<!--Advisor-->
<object id="theDbAccessAdvisor"
type="Spring.Aop.Support.RegularExpressionMethodPointcutAdvisor, Spring.Aop">
<property name="Pattern" value="Aspect*"/>
<property name="Advice" ref="theDbAccessAdvice"/>
</object>
<object id="theLogAdvisor"
type="Spring.Aop.Support.RegularExpressionMethodPointcutAdvisor, Spring.Aop">
<property name="Pattern" value="Aspect*"/>
<property name="Advice" ref="theLogAdvice"/>
</object>
但是建议被解雇之前的结果相同,但不会抛出建议。
我尝试过使用Spring.NET的ExceptionHandleAdvice方面,抛出相同的异常,但建议没有。
<object id="exAdvice"
type="Spring.Aspects.Exceptions.ExceptionHandlerAdvice, Spring.Aop">
<property name="ExceptionHandlers">
<list>
<value>on exception name DbException swallow</value>
</list>
</property>
</object>
这个项目对我来说很神奇我在这里上传了所有VS项目:
http://hotfile.com/dl/135485464/93558e0/Log4Net.7z.html
这是例外的stackTrace:
在Aspect.Managers.DbCustomerManager.GetCustomerById(Int64 id)中 E:\ C# 项目\研究\ SPRING.NET \ Study.Spring.Net \ \方面记录\ log4net的\经理\ DbCustomerManager.cs:行 20点到 Spring.Reflection.Dynamic.SafeMethod.Invoke(Object中的_dynamic_Aspect.Managers.DbCustomerManager.GetCustomerById(Object,Object []) target,Object [] arguments)at Spring.Aop.Framework.DynamicMethodInvocation.InvokeJoinpoint()at Spring.Aop.Framework.AbstractMethodInvocation.Proceed()at Spring.Aspects.Exceptions.ExceptionHandlerAdvice.Invoke(IMethodInvocation 调用)
此外,如果我尝试捕获这样的异常:
try
{
var springContext = ContextRegistry.GetContext();
var dbMgr = (IDbCustomerManager)springContext["theDbCustomerManager"];
dbMgr.GetCustomerById(1);
}
catch (Exception ex)
{
Console.WriteLine("{0}\n{1}", ex.GetType(), ex.Message);
}
不可能..系统显示消息是未处理的异常....
答案 0 :(得分:1)
我测试了你的包裹。一切正常(我正在使用v1.3.2)。
AfterThrows
建议捕获异常(使用断点)但不会被忽略。
这是我的配置:
public void AfterThrowing(MethodInfo method, Object[] args,
Object target, DbException exception)
{
Console.WriteLine(exception.Message);
}
<!--DAO-->
<object id="theCustomerDao"
type="Aspect.Dao.CustomerDao"/>
<!--Business object-->
<object id="theDbCustomerManager"
type="Aspect.Managers.DbCustomerManager">
<!--<property name="CustomerDao" ref="theCustomerDao"/>-->
</object>
<!--Advices-->
<object id="theLogAdvice"
type="Aspect.LogExThrowsAdvice, Log4NetInSpringNet"/>
<!--Proxy creator-->
<object type="Spring.Aop.Framework.AutoProxy.TypeNameAutoProxyCreator, Spring.Aop">
<property name="TypeNames" value="Aspect.Managers.DbCustomerManager*"/>
<property name="InterceptorNames">
<list>
<value>theLogAdvice</value>
</list>
</property>
</object>
答案 1 :(得分:1)
如果你把你的代码与bbaia的配置结合起来,那么我认为你已经到了一半了。
从您的问题和评论中,我了解您想要吞下DbException
。
请注意,一般来说,您永远不会希望您的记录器吞下异常,但为了问题,请假设您这样做 - 但我保证您永远不会在生产环境中执行此操作: - )
我建议您稍微调整一下LogExThrowsAdvice
:
public class LogExThrowsAdvice : Spring.Aspects.Exceptions.ExceptionHandlerAdvice, IThrowsAdvice
{
public void AfterThrowing(MethodInfo method, Object[] args,
Object target, Exception exception)
{
Console.WriteLine(exception.Message);
}
}
继承ExceptionHandlerAdvice
允许您指定how to handle thrown exceptions,例如吞下它。
然后拿bbaia的配置并为它添加一个事件处理程序:
<object id="theLogAdvice"
type="Aspect.LogExThrowsAdvice, Log4NetInSpringNet">
<property name="exceptionHandlers">
<list>
<value>on exception name DbException swallow</value>
</list>
</property>
</object>
现在吞下了所有DbException
。
关于你在Visual Studio中如何引发的问题:你的VS是否可以设置为“中断抛出的异常”?转到调试 - &gt;例外和_un_check公共语言运行时异常的Thrown复选框。
请注意,如果您选中此选项,则在引发异常时仍可继续:程序不会崩溃,因为会处理异常。