Spring AOP - 方面循环执行

发布于 2024-12-20 07:27:58 字数 1485 浏览 1 评论 0 原文

首先,我需要说我是 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 :)
    }
}

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

寻找一个思念的角度 2024-12-27 07:27:58

答案#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
}

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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文