如何在Spring Boot aop @Around函数中创建事务?

拒绝:

我想通过使用Spring Boot AOP实现授权方法。最初的想法是,如果从REST调用返回的返回对象未通过授权检查,它将抛出未授权的异常。

我正在这样做:

@Aspect
@Component
public class AuthAspect {
  @Around("AllRestExecPoint()")
  public Object auth(ProceedingJoinPoint point) throws Throwable {
    Object returnObject = point.proceed();
    if (!checkAuthorization(returnObject)) {
      throw new UnauthException();
    }
    return returnObject;
  }
}

但是,问题是,如果此REST服务将对我的数据库执行一些INSERT或UPDATE,它将在我的授权检查之前提交。因此,UnauthException将抛出,但事务仍被提交。

我想尝试在proceed()调用之前手动创建事务并在返回之前提交它的第一次尝试,但是失败了。

@Aspect
@Component
public class AuthAspect {
  private final EntityManager em;

  @Autowired
  public AuthAspect(EntityManager em) {
    this.em = em;
  }

  @Around("AllRestExecPoint()")
  public Object auth(ProceedingJoinPoint point) throws Throwable {
    em.getTransaction().begin();

    Object returnObject = point.proceed();
    if (!checkAuthorization(returnObject)) {
      throw new UnauthException();
    }

    em.getTransaction().commit();

    return returnObject;
  }
}

这将导致java.lang.IllegalStateException: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead

我在互联网上搜索了一些答案,需要修改web.xml文件,但是我不想使用xml进行配置。

然后马库斯:

从标签来看,您正在使用Spring Boot。Spring Boot提供了一个预配置的TransactionTemplate,如果您手动想要控制事务,可以使用它。

而不是将其EntityManger注入您的方面并将代码包装在其中。

@Aspect
@Component
public class AuthAspect {
  private final TransactionTemplate tx;

  public AuthAspect(TransactionTemplate tx) {
    this.tx = tx;
  }

  @Around("AllRestExecPoint()")
  public Object auth(ProceedingJoinPoint pjp) throws Throwable {

    return tx.execute(ts -> this.executeAuth(pjp));   
  }

  private Object executeAuth(ProceedingJoinPoint pjp) {
    Object returnObject;
    try {
      returnObject  = pjp.proceed();
    } catch (Throwable t) {
      throw new AopInvocationException(t.getMessage(), t);
    }
    if (!checkAuthorization(returnObject)) {
      throw new UnauthException();
    }
    return returnObject;
  }
}

这将在事务内部执行逻辑。我将实际的逻辑移到一个方法上,以便lambda可以是单个方法而不是代码块。(个人偏好/最佳实践)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章