【问题标题】:@Around pointcut invokes method two times@Around 切入点调用方法两次
【发布时间】:2015-02-11 06:33:15
【问题描述】:

有时我的 API 会抛出异常,该服务器无法处理我的请求。我决定创建将重新调用 API 调用的 AOP 方面。比如 5 次以后如果还是不行就抛出异常。

请看我的 AOP 课程。这不是一个完整的身体,但我希望你能够理解发生了什么:

@Aspect
public class RetryRequestExecutor {

    ....

    @Around("@annotation(com.test.RequestRetriable)")
    public Object retryApiRequest(ProceedingJoinPoint point) throws Throwable {
        int numAttempts = 0;
        ServiceException lastException;
        do {
            numAttempts++;
            try {
                preInvokeLog(point);
                Object retValue = point.proceed();
                postInvokeLog(point);
                return retValue;
            } catch (ServiceException e) {
                lastException = handleServiceException(point, numAttempts, e);
            }
        } while (numAttempts <= maxRetries);
        throw lastException;
    }

    ....
}

这是我的服务类:

public class UserApiImpl implements UserApi {

    ...

    @Override
    public List<DomainUser> retrieveSuspendedUsers() throws Exception{
        LOG.debug("Retrieving suspended users.");

        ...

        List<DomainUser> users = new ArrayList<DomainUser>(64);
        do {
            //Invoke API. AOP invoke it two times! 
            currentPage = getUsers(retrieveUrl);
                    ...
                    URL nextLink = currentPage.getNextLink();
                    if (nextLink == null){
                        break;
                    }
            ...
        } while (nextLink != null);

        return users;
    }

    @Override
    @RequestRetriable
    public UserFeed getUsers(URL feedUrl) throws Exception {
        return userService.getFeed(feedUrl, UserFeed.class);
    }

    ...
}

如您所见,我只注释了getUsers 方法。方法retrieveSuspendedUsers没有注释。

Spring 配置如下:

<aop:aspectj-autoproxy/>

现在,当我直接调用 getUsers 方法时,一切正常 - AOP 只调用它一次。但是当我调用retrieveSuspendedUsers 方法时 - AOP 为每个页面调用它两次(我逐页检索用户,页面大小等于 100)。我可以在日志中看到以下几行:

2013-03-11 13:06:40,179 DEBUG [pool-2-thread-1] Invoke API request getUsers with arguments [https://domain.com/user/2.0/]
2013-03-11 13:06:40,180 DEBUG [pool-2-thread-1] Invoke API request getUsers with arguments [https://domain.com/user/2.0/]
2013-03-11 13:06:41,745 DEBUG [pool-2-thread-1] Invoke API request getUsers with arguments [https://domain.com/user/2.0/] finished successfully
2013-03-11 13:06:41,745 DEBUG [pool-2-thread-1] Invoke API request getUsers with arguments [https://domain.com/user/2.0/] finished successfully

API 调用非常耗时,我想避免额外的、不必要的调用。如何解决此问题?

【问题讨论】:

  • 你能同时记录调用者线程名称吗
  • nextLink的赋值是如何处理的?
  • 你的建议似乎很好,我怀疑有人打电话给getUsers 两次,如果你可以记录调用者线程,我们可以验证这一点
  • 我已将线程名称添加到日志中。 @matsev - 我添加了显示如何检索下一个链接的源代码。

标签: java aspectj spring-aop


【解决方案1】:

AFAIK 切入点拦截在切入点建议的callexecution 事件中调用。您可以过滤以匹配切入点中的方法 execution

@Around("execution(* *(..)) && @annotation(com.test.RequestRetriable)")

【讨论】:

  • 你是对的!有用!你让我今天一整天都感觉很好!现在它只调用一次,即使在我的“retrieveSuspendedUsers”方法中也是如此。我认为它默认仅适用于“执行”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-15
  • 2021-11-04
  • 1970-01-01
相关资源
最近更新 更多