假设我的服务的所有公共方法都有一个方面包装器,它将实体从数据库中分离出来,然后再将它们返回给控制器:
@Around("execution(public * *(..)) && @within(org.springframework.stereotype.Service)")
当一个服务直接调用另一个服务时,也会触发此包装器。例如:
@Service
class ServiceA {
@Autowired
ServiceB b;
public void foo() {
b.bar();
}
}
@Service
class ServiceB {
public void bar() {
}
}
当我调用ServiceA.foo()
时,包装器也会触发围绕bar()
的嵌套调用。
它应该触发foo()
的呼叫,而不是bar()
。我怎么能避免这个?
答案 0 :(得分:1)
我有时会使用ThreadLocal变量来解决这类问题。尝试类似:
@Aspect
public class DetacherAspect {
private final ThreadLocal<Object> threadLocal = new ThreadLocal<Object>();
@Around("execution(public * *(..)) && @within(org.springframework.stereotype.Service)")
public Object execute(ProceedingJoinPoint pjp) throws Throwable {
boolean isNested = threadLocal.get() != null;
if (!isNested) {
// Set some object (better create your own class) if this is the first service
threadLocal.set(new Object());
}
try {
... // Your aspect
} finally {
// Clean thread local variables
if (!isNested) {
threadLocal.remove();
}
}
}
}
显然,这只适用于所有调用都在同一个线程中完成的情况。线程局部变量也有一些其他缺点,并且很好地阅读它们。
答案 1 :(得分:0)
我只使用我的iPad,所以我现在无法测试,但你可以尝试以下方式:
pointcut myCalls() :
execution(public * *(..)) && @within(org.springframework.stereotype.Service);
pointcut myCallsNonRecursive() :
myCalls() && !cflowbelow(myCalls())
around() : myCallsNonRecursive() {
// ...
}
对于AspectJ原生语法很抱歉,我对它更熟悉。