Spring AOP - 方面循环执行

时间:2011-12-09 13:06:44

标签: spring aop spring-aop

首先,我需要说我是Spring AOP的新手(嗯,我是AOP的新人)。 在我的应用程序中,我有服务类,由方面建议,unitil这一点很好。每个人都会触发方面。但我需要从我的方面调用该服务方法,并且存在问题。我的Aspect是(逻辑上)触发每个调用和每个结束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 个答案:

答案 0 :(得分:2)

回答#1:仅呼叫建议的方法(建议周围)

如果您将服务重新发送回自己的方面,那么您仍然在调用Spring的代理机制,包括您已应用于服务的AOP方面。

参见Spring AOP章节中的“围绕建议”:

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
}