Spring AOP - выполнение аспектного цикла - PullRequest
0 голосов
/ 09 декабря 2011

в первую очередь я должен сказать, что я новичок в Spring AOP (ну, я вообще новичок в AOP).В моем приложении у меня есть класс обслуживания, который рекомендуется по аспектам, но этот момент очень хорош.Аспект срабатывает, каждый работает.Но мне нужно вызывать этот сервисный метод с моей стороны, и есть проблема.Мой аспект (логично) срабатывает для каждого вызова и каждого конца ошибки StackOwerflow.

Можно ли предотвратить этот аспект зацикливания?

У меня есть идея создать интерфейс (или класс) IAspectSandbox, и вызовы методов из класса, которые будут реализовывать этот интерфейс, не вызывают аспектов.Но я действительно не знаю, как достичь этой цели:)

Моя схема занятий:

@Service
public class MyService 
{
  public BarObject update( FooObject item )
  {
      BarObject barObject = new BarObject();
      // save FooObject to database and detect changes against old row
      // information about fields, that was changed is in BarObject
      return barObject;
  }
}

--------------------------------------------------------------------------

@Aspect
public class MyServicePointcut 
{
    @Pointcut("execution(*  cz.package.service.MyService.update(..))")  
    public void myServiceItemChanged() {}   
}

--------------------------------------------------------------------------

@Component
@Aspect
public class PraceZadaniChangeAspect 
{

  @AutoWire
  private MyService myService;


  @AfterReturning("cz.package.pointcuts.MyServicePointcut.myServiceItemChanged()", returning = "returnVal")  
    public void execute( BarObject returnVal )
    {
        // do something with BarObject ... mostly check changes
            // .....
            // .....
            // at the end I need to save changes
        myService.update( returnVal.getFooObject() ); // after this call is this aspect triggered again. I know why, but I don't want to :)
    }
}

1 Ответ

2 голосов
/ 09 декабря 2011

Ответ № 1: Вызов только рекомендованного метода (Around Advice)

Если вы автоматически подключаете свой сервис обратно к своему аспекту, вы все равно задействуете прокси-механизм Spring, включая аспект AOP, который вы применили к своему сервису.

См. «Вокруг совета» в главе AOP Spring:

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-ataspectj-around-advice

В основном, сделайте что-то вроде этого:

@AfterReturning("...")
public void execute(ProceedingJoinPoint p, BarObject returnVal)
{
    // do something with BarObject
    // ...
    // call original method with original args
    p.proceed(p.getArgs());
}

Я не уверен на 100% в коде, но proceed() должен вызывать целевой метод напрямую, без рекурсивного вызова прокси-сервера AOP.

Ответ № 2: вызов нескольких методов целевого объекта

Если вам нужно вызвать несколько методов из этого сервисного объекта в вашем аспекте, вам потребуется доступ к незафиксированному объекту через getTarget():

@AfterReturning("...")
public void execute(JoinPoint p, BarObject returnVal)
{
    // do something with BarObject
    // ...
    // call various service methods without triggering this AOP proxy again
    // by using getTarget() to get the unproxied object:
    MyService myService = (MyService) p.getTarget();
    myService.update(...);               // does not trigger AOP interceptor
    myService.otherMethod(...);          // neither does this
    myService.thirdMethod(...);          // nor this
}
...