Обрабатывать с исключением на объекте auto proxy / proxy factory - PullRequest
1 голос
/ 19 ноября 2011

Я начинаю изучать среду 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));
        }

    }
}

Во-вторых, я определил Advice для обработки исключений.

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

    }
}

И, наконец, я присоединяюсь к бизнес-объекту togheter и совету с прокси.

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

Исключение выдается, метод AfterThrowing из LogExThrowsAdvice не вызывается.

Я пытаюсь изменить тип рекомендации для типа 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>

Но тот же результат до того, как совет уволен, но не выдает совет.

Я пытался использовать также аспект ExceptionHandleAdvice из Spring.NET, выдается то же исключение, но не совет.

 <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

Вот стек исключений:

в Aspect.Managers.DbCustomerManager.GetCustomerById (Int64 id) в E: \ C # ПРОЕКТЫ \ ИССЛЕДОВАНИЯ \ SPRING.NET \ Study.Spring.Net \ Аспекты \ Logging \ Log4Net \ Менеджеры \ DbCustomerManager.cs: линия 20 в _dynamic_Aspect.Managers.DbCustomerManager.GetCustomerById (Object, Object []) в Spring.Reflection.Dynamic.SafeMethod.Invoke (Object target, Object [] arguments) в Spring.Aop.Framework.DynamicMethodInvocation.InvokeJoinpoint () в Spring.Aop.Framework.AbstractMethodInvocation.Proceed () в 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);
        }

Это невозможно ... системное сообщение об ошибке является необработанным исключением ....

Ответы [ 2 ]

1 голос
/ 20 ноября 2011

Если вы возьмете свой код и объедините его с конфигурацией bbaia, то я думаю, что вы на полпути.

Из вашего вопроса и комментариев я понимаю, что вы хотите проглотить DbException s.Обратите внимание, что, вообще говоря, вы никогда не захотите, чтобы ваш регистратор глотал исключения, но ради вопроса предположите, что вы это делаете - но пообещайте мне, что вы никогда не будете делать это в производственной среде: -)

Я предлагаю вам немногонастройте 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 s проглочены.

Относительно вашего вопроса о том, как это все еще генерируется в Visual Studio: может ли быть так, что ваш VS настроен так, чтобы "разбить выброшенное исключение"?Перейдите в раздел «Отладка -> Исключения» и установите _un_check флажок «Брошено» для общеязыковых исключений времени выполнения.

Обратите внимание, что если оставить этот флажок, вы сможете продолжить работу при возникновении исключения: программа не завершится сбоем, поскольку исключениеобрабатывается.

1 голос
/ 20 ноября 2011

Я проверил вашу посылку. Все отлично работает (я использую 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>
...