Reputation: 1329
I use in my Spring boot project aspect that is fired on every public method in annotated class:
@Aspect
@Component
public class DeletedAwareAspect {
@Before("@within(com.example.DeleteAware)")
public void aroundExecution(JoinPoint pjp) throws Throwable {
//... some logic before
}
@After("@within(com.example.DeleteAware)")
public void cleanUp(JoinPoint pjp) throws Throwable {
//... some logic after
}
}
Usage of that aspect is below:
@DeleteAware
@Service
public class MyService {
public void foo() {}
}
@DeleteAware
@Service
public class MyAnotherService {
@Autowired
private MyService service;
public void anotherFoo() {}
public void VERY_IMPORTANT_METHOD() {
service.foo();
}
}
MyService.foo() and MyAnotherService.anotherFoo() works as expected. But here is the problem - if method wrapped by aspect is called by another aspected method (like VERY_IMPORTANT_METHOD()), I dont want to fire aspect twice, but only once. How to check from Aspect whether method is called inside another aspected method?
Upvotes: 0
Views: 1215
Reputation: 67297
Like I said, if you would switch to native AspectJ you could use percflow()
aspect instantiation and/or cflow()
pointcuts, but I will not explain that here in detail because you are looking for a Spring AOP solution. Like R.G said, it is actually quite simple: Use a thread-local counter for the aspect nesting level and only do something (e.g. deleting something in the after advice) if the counter is zero.
@Aspect
@Component
public class DeletedAwareAspect {
private ThreadLocal<Integer> nestingLevel = ThreadLocal.withInitial(() -> 0);
@Before("@within(com.example.DeleteAware)")
public void aroundExecution(JoinPoint pjp) {
int level = nestingLevel.get() + 1;
nestingLevel.set(level);
System.out.println("BEFORE " + pjp + " -> " + level);
}
@After("@within(com.example.DeleteAware)")
public void cleanUp(JoinPoint pjp) {
int level = nestingLevel.get() - 1;
nestingLevel.set(level);
System.out.println("AFTER " + pjp + " -> " + level);
if (level == 0)
System.out.println("Deleting something");
}
}
Upvotes: 1