首先,我需要说我是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 :)
}
}
答案 0 :(得分:2)
回答#1:仅呼叫建议的方法(建议周围)
如果您将服务重新发送回自己的方面,那么您仍然在调用Spring的代理机制,包括您已应用于服务的AOP方面。
参见Spring AOP章节中的“围绕建议”:
基本上,做这样的事情:
@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
}