处理自动代理/代理工厂对象上的异常

发布于 2024-12-17 06:39:21 字数 6162 浏览 1 评论 0原文

我开始学习 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

Advice:

  <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);

在建议被解雇之前但抛出建议不是吗?为什么?仅抛出异常。

对我来说,它的真正运作方式很神奇。

我尝试使用顾问而不是建议:

  <!--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\Aspects\Logging\Log4Net\Managers\DbCustomerManager.cs:行 20 点 _dynamic_Aspect.Managers.DbCustomerManager.GetCustomerById(Object , Object[] ) 在 Spring.Reflection.Dynamic.SafeMethod.Invoke(Object 目标,Object[] 参数)位于 Spring.Aop.Framework.DynamicMethodInitation.InvokeJoinpoint() 在 Spring.Aop.Framework.AbstractMethodInitation.Proceed() 在 Spring.Aspects.Exceptions.ExceptionHandlerAdvice.Invoke(IMethodInitation 调用)

另外,如果我尝试捕获类似这样的异常:

        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);
        }

这是不可能的..系统显示消息是未处理的异常....

I start learning Spring.NET framework and I am very confusing with behavior of proxy, auto-proxy and exception handling.

for example I defined simple business object and from this object I will throw custom exception.

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));
        }

    }
}

Second I defined Advice for handling with exception.

public class LogExThrowsAdvice:IThrowsAdvice
{
    public void AfterThrowing(MethodInfo method, Object[] args,
            Object target, DbException exception)
    {
        Console.WriteLine(exception.Message);

    }
}

And last I join togheter business object and advice with proxy.

In app.confing

Advice:

  <object id="theLogExThrowsAdvice"
          type="Aspect.LogExThrowsAdvice, Log4NetInSpringNet"/>

Auto-Proxy

  <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>

And test it:

            var springContext = ContextRegistry.GetContext();
            var dbMgr = (IDbCustomerManager)springContext["theDbCustomerManager"];
            dbMgr.GetCustomerById(1);

Exception is throwed, method AfterThrowing from LogExThrowsAdvice is not calling.

I try changed type of advice for type 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
}

and in 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 is fire but ThrowsAdvice no. Why?

I tried change auto proxy for proxy object factory and tried proxying interfaces 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);

Before advice is fired but throws advice are not? why? Only exception is throwed.

For me is magic how it really work.

I tried used Advisors instead advices:

  <!--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>

But same result before advice is fired but throws advice not.

I tried use also ExceptionHandleAdvice aspect from Spring.NET same exception is throwed but advice not.

 <object id="exAdvice"
          type="Spring.Aspects.Exceptions.ExceptionHandlerAdvice, Spring.Aop">
    <property name="ExceptionHandlers">
      <list>
        <value>on exception name DbException swallow</value>
      </list>
    </property>
  </object>

This project is for me magic I upload all VS project here:

http://hotfile.com/dl/135485464/93558e0/Log4Net.7z.html

Here is stackTrace of exception:

at Aspect.Managers.DbCustomerManager.GetCustomerById(Int64 id) in
E:\C#
PROJECTS\STUDY\SPRING.NET\Study.Spring.Net\Aspects\Logging\Log4Net\Managers\DbCustomerManager.cs:line
20 at
_dynamic_Aspect.Managers.DbCustomerManager.GetCustomerById(Object , Object[] ) at Spring.Reflection.Dynamic.SafeMethod.Invoke(Object
target, Object[] arguments) at
Spring.Aop.Framework.DynamicMethodInvocation.InvokeJoinpoint() at
Spring.Aop.Framework.AbstractMethodInvocation.Proceed() at
Spring.Aspects.Exceptions.ExceptionHandlerAdvice.Invoke(IMethodInvocation
invocation)

Also if I try catch exception something like this:

        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);
        }

It is not possible..system show message is unhandled exception....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

初与友歌 2024-12-24 06:39:21

我测试了你的包裹。一切正常(我使用的是 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>

I tested your package. Everything works fine (I'm using v1.3.2).
The exception is caught by the AfterThrows advice (use a breakpoint) but not ignored.
Here is my config:

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>
獨角戲 2024-12-24 06:39:21

如果你把你的代码和 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 允许您指定 如何处理抛出的异常,例如吞下它。
然后获取 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 是否设置为“抛出异常时中断”?转到调试->异常并取消选中公共语言运行时异常的“抛出”复选框。

请注意,如果保持选中此项,则在引发异常时仍然可以继续:程序不会崩溃,因为异常已被处理。

If you take your code and combine it with bbaia's config, then you're halfway there I think.

From your question and comments, I understand that you want to swallow the DbExceptions.
Note that generally speaking, you'd never want your logger swallow exceptions, but for the question's sake assume you do - but promise me you'll never do this in a production environment :-)

I suggest you slightly adjust your LogExThrowsAdvice to:

public class LogExThrowsAdvice : Spring.Aspects.Exceptions.ExceptionHandlerAdvice, IThrowsAdvice
{
    public void AfterThrowing(MethodInfo method, Object[] args,
        Object target, Exception exception)
    {
        Console.WriteLine(exception.Message);

    }
}

Inheriting from ExceptionHandlerAdvice allows you to specify how to handle thrown exceptions, for instance swallow it.
Then take bbaia's config and add an event handler to it:

<object id="theLogAdvice"
        type="Aspect.LogExThrowsAdvice, Log4NetInSpringNet">
  <property name="exceptionHandlers">
    <list>
      <value>on exception name DbException swallow</value>
    </list>
  </property>
</object>

Now all DbExceptions are swallowed.

With respect to your question as to how this still throws in Visual Studio: could it be that your VS is set to "break on a thrown exception"? Go to Debug -> Exceptions and _un_check the Thrown checkbox for Common Language Runtime Exceptions.

Note that if you keep this checked, you can still continue when the exception is raised: the program will not crash, because the exception is handled.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文