微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如果方法被另一个带注释的方法调用,则检查 Spring AOP

如何解决如果方法被另一个带注释的方法调用,则检查 Spring AOP

我在我的 Spring boot 项目中使用了在带注释的类中的每个公共方法上触发的方面:

@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())调用,我不想触发方面两次,但只触发一次。 如何从Aspect检查方法是否在另一个切面方法中被调用

解决方法

就像我说的,如果您要切换到原生 AspectJ,您可以使用 percflow() 方面实例化和/或 cflow() 切入点,但我不会在这里详细解释,因为您正在寻找 Spring AOP 解决方案。就像 R.G 所说,它实际上非常简单:在方面嵌套级别使用线程本地计数器,并且仅在计数器为零时才执行某些操作(例如,在 after 通知中删除某些内容)。

@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");
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。