【问题标题】:Spring AOP - aspect loop executionSpring AOP - 方面循环执行
【发布时间】:2011-12-12 21:28:07
【问题描述】:

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

【问题讨论】:

    标签: spring aop spring-aop


    【解决方案1】:

    答案 #1:仅调用建议方法(围绕建议)

    如果你将你的服务自动装配回你的切面,你仍然在调用 Spring 的代理机制,包括你应用到你的服务的 AOP 切面。

    参见 Spring AOP 章节中的“Around Advice”:

    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
    }
    

    【讨论】:

    • 我明白你的意思,但我正在考虑编写切入点规则。以某种方式排除来自特定类(或实现特定接口的类)的调用。但我不确定这是否可能。
    • 您可以使用 '!' 将切入点中的类排除在外。检查参考 here
    • 是的,我知道,但我需要排除调用该服务类方法的类。我需要将所有方法调用从我的方面排除到服务类。我不确定这在 Spring AOP 中是否可行。
    • 请参阅上面添加到响应中的答案 #2 - 我认为这回答了您的问题。另一方面,如果您在一个对象上定义了切入点并试图避免 AOP 代理到另一个对象:(a) 您可以通过创建自己的代理对象来做到这一点 - 代理对象获取 AOP 建议并且只是将每个方法委托给原始的 MyService 对象,该对象没有任何 AOP 建议,并且 (b) 您可能需要重新考虑代码的结构。
    • @BobG 你是我的英雄,它真的很有效。谢谢你,你帮了我很多。事实是,我不确定我是否很好地使用了方面。在我的应用程序中,我需要监听一些事件,例如“记录 A 已更改,做某事或调用某事”。起初我创建了自己的事件监听器实现,但我并不满意。在那之后,我在 spring 文档中阅读了关于 AOP 的内容,对此我感到很高兴。这正是我所需要的。非常好的解耦“监听器”,被建议的对象不知道方面,我不需要硬编码一些钩子来触发监听器。
    猜你喜欢
    • 2011-09-20
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多