Spring.NET.AOP - ExceptionHandlerAdvice не заменяет пользовательское исключение - PullRequest
3 голосов
/ 17 ноября 2011

это мой первый, а также я новичок в Spring.NET, а также АОП.

Я бы хотел использовать Aspect for Exception Hadling для замены, переноса и изменения моих пользовательских исключений.

Сначала я определил некоторую сущность и DAO. Из метода Save в 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 только на System.ArgumentException.

Я не уверен, является ли ExceptionHandlerAdvice авто-прокси, а также я не знаю, как он определил цели.

Я полагаю, что он использует SpEL для определения правил, а когда есть какое-то исключение, он выдает контрольный список. Хорошо, этот тип исключения находится в списке, к которому я буду применять совет.

Может кто-нибудь объяснить мне, как этот аспект определил цели? Например, я хотел бы применить этот аспект только для нескольких объектов, а не для всех.

Я использую справочную документацию, Глава 14.3 Обработка исключений, но я не смог найти эту информацию.

Вот файл 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>

Моя основная проблема заключается в том, что если я вызываю метод Save в DAO, он выбрасывает тип исключения 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,

Также я пытался использовать DSL для определенных правил, когда применяются рекомендации:

on exception (#e is T(ExceptionHandlingTutorial.CustomerException) translate new System.ArgumentException('XChange, Method Name'+ #method.Name, #e))

Но все равно это тип исключительной ситуации CustomerException.

Спасибо за помощь.

1 Ответ

2 голосов
/ 17 ноября 2011

Spring.NET aop динамически создает прокси для объектов, к которым вы хотите применить совет.Spring.NET возвращает этот прокси, когда вы делаете var customerDao = (ICustomerDao)context["customerDao"];.Поэтому при правильной настройке вы получаете не экземпляр CustomerDao, а прокси-сервер aop от Spring, реализующий интерфейс ICustomerDao.Этот прокси перехватывает вызов к Save(...) и применяет ваш совет по обработке исключений.

Однако вы не настроили ProxyFactory, поэтому при вызове вы не получите прокси, но экземпляр CustomerDaovar 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" />
...