如果方法被另一个带注释的方法调用,则签入 Spring AOP
Check in Spring AOP if method is called by another annotated method
我在我的 Spring 引导项目方面使用了注释 class 中的每个 public 方法触发的方面:
@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
}
}
该方面的用法如下:
@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() 和 MyAnotherService.anotherFoo() 按预期工作。但这就是问题所在——如果被方面包装的方法被另一个方面方法调用(比如 VERY_IMPORTANT_METHOD()),我不想触发方面两次,而只是一次。
如何从切面检查方法是否在另一个切面方法内部被调用?
就像我说的,如果你想切换到原生 AspectJ,你可以使用 percflow()
方面实例化 and/or cflow()
切入点,但我不会在这里详细解释,因为你是寻找 Spring AOP 解决方案。就像 R.G 说的,其实很简单:对方面嵌套级别使用一个线程本地计数器,并且只在计数器为零时才做一些事情(例如,删除 after advice 中的一些东西)。
@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");
}
}
我在我的 Spring 引导项目方面使用了注释 class 中的每个 public 方法触发的方面:
@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
}
}
该方面的用法如下:
@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() 和 MyAnotherService.anotherFoo() 按预期工作。但这就是问题所在——如果被方面包装的方法被另一个方面方法调用(比如 VERY_IMPORTANT_METHOD()),我不想触发方面两次,而只是一次。 如何从切面检查方法是否在另一个切面方法内部被调用?
就像我说的,如果你想切换到原生 AspectJ,你可以使用 percflow()
方面实例化 and/or cflow()
切入点,但我不会在这里详细解释,因为你是寻找 Spring AOP 解决方案。就像 R.G 说的,其实很简单:对方面嵌套级别使用一个线程本地计数器,并且只在计数器为零时才做一些事情(例如,删除 after advice 中的一些东西)。
@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");
}
}