Peter
Peter

Reputation: 135

Spring AOP - aspect loop execution

in first and foremost i need to say that I'm new in Spring AOP (well, I'm new in AOP at all). In my application I have service class which is advised by aspect, unitil this point is everyting fine. Aspect is triggered, everyting works. But I need to call that service method from my aspect, and there is problem. My Aspect is (logicaly) triggered for each call and everyting end on StackOwerflow error.

It is possible to prevent that aspect looping ?

I have idea to create IAspectSandbox interface (or class) and method invocations from class which will implement this interface do not trigger aspects. But I really don't know how to achieve this goal :)

My class schema:

@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 :)
    }
}

Upvotes: 0

Views: 2146

Answers (1)

BobG
BobG

Reputation: 2171

Answer #1: Calling Advised Method Only (Around Advice)

If you autowire your service back into your aspect, you're still invoking Spring's proxy mechanism, including the AOP aspect that you've applied to your service.

See "Around Advice" in the Spring AOP chapter:

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

Basically, do something like this:

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

I am not 100% sure on the code, but proceed() should call the target method directly without invoking the AOP proxy recursively.

Answer #2: Calling Multiple Target Object Methods

If you need to call multiple methods from that service object within your aspect, you'll need access to the unproxied object via 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
}

Upvotes: 2

Related Questions