Атрибут транзакции spring.net работает только для методов, вызываемых извне

У вас есть класс обслуживания, настроенный с помощью Spring.NET. DoWork выполняет две задачи, которые должны выполняться в двух транзакциях. Но Spring.NET, похоже, не вызывает никакого транзакционного поведения АОП. Я должен аннотировать DoWork() с атрибутом Transaction, но это объединит обе задачи в одну транзакцию, чего я не хочу. Как я могу решить проблему?

IMyService service.DoWork();

public class MyServiceImpl : IMyService
{

public DoWork()
{
  Task1();
  Task2();
}

[Transaction(ReadOnly=false)]
protected void Task1()
{
  // do it
}

[Transaction(ReadOnly=false)]
protected void Task2()
{
  // do it
}
}

person Max    schedule 15.01.2011    source источник
comment
Относительно этот аналогичный вопрос I ответил месяц назад. Ответ A. правильный, и связанный ответ может дать вам дополнительную справочную информацию.   -  person Marijn    schedule 27.01.2011


Ответы (2)


Как я вижу здесь, Spring.NET использует интерфейс- на основе динамического проксирования для достижения своей «АОП-ности». Прокси на основе интерфейса работают как шаблон декоратора. Методы Task1 и Task2 не являются частью интерфейса, поэтому Spring.NET не может декорировать вызовы этих методов, поэтому он не может применять какое-либо поведение.

Изменение Task1 и Task2 на общедоступные и добавление их в интерфейс также не поможет в вашем сценарии, так как DoWork вызывает this.Task1() и this.Task2(), где this будет обозначать конкретный объект, а не прокси-сервер AOP.

Единственное решение в вашем сценарии — использовать другой метод АОП, либо динамическое проксирование на основе базового класса во время выполнения (я не знаю, позволяет ли это Spring.NET, это можно сделать, например, с помощью Unity Interception) или переплетение во время компиляции (например, PostSharp).

person NOtherDev    schedule 19.01.2011
comment
Это решение, но не единственное решение. Кроме того, похоже, что spring.net поддерживает прокси-сервер на основе наследования из версии 1.3.1, что может помочь. - person Marijn; 28.01.2011

А. прав в своем наблюдении.

Однако я бы предложил выделить две задачи в два отдельных класса, которые внедряются в класс, содержащий процедуру DoWork().

public class MyServiceImpl : IMyService
{
  // use property injection to set Task1 and Task2
  public DoWork()
  {
    Task1.Process();
    Task2.Process();
  }

}

public class Task1
{
  [Transaction(ReadOnly=false)]
  protected void Process()
  {
    // do it
  }
}

public class Task2
{
  [Transaction(ReadOnly=false)]
  protected void Process()
  {
    // do it
  }
}
person Marijn    schedule 27.01.2011