我对我编码的Aspect有一个问题:
@Aspect
@Component
public class MyAudit {
@Pointcut("@annotation(requestMapping)")
public void controller(RequestMapping requestMapping) {
}
@Around("controller(requestMapping)")
public Object around(ProceedingJoinPoint pjp, RequestMapping requestMapping) throws Throwable {
...
在代码的一个路径中,我正在查找授权,我需要将信息返回给用户而不执行该方法。基本上,我需要简化流程。
我有这样的代码:
log.warn("Not permitted per policy. Returning without executing: " + authError);
Map<String,String> responseBody = new HashMap<>();
responseBody.put("path",request.getContextPath());
responseBody.put("message",authError);
return new ResponseEntity<>(responseBody,HttpStatus.OK);
问题在于,当我返回ResponseEntity时,它会回到我的'around'方法中。不知道为什么它会再次执行。
另一个线程上有人提到我不应该将其注释为@Component,但我尝试删除它,当我这样做时,@ Around方法根本不会执行。
有谁可以指出我做错了什么?
更新:
这是完整的类,其中包含一些与业务特定项目相关的代码。
import com.ge.aviation.paasport.model.Audit;
import com.ge.aviation.paasport.repository.AuditRepository;
import com.ge.aviation.paasport.util.SecurityUtils;
import static com.google.common.base.Strings.isNullOrEmpty;
import java.lang.annotation.Annotation;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import org.apache.http.HttpResponse;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@Aspect
@Component
public class MyAudit {
@Pointcut("@annotation(requestMapping)")
public void controller(RequestMapping requestMapping) {
}
@Around("controller(requestMapping)")
public Object around(ProceedingJoinPoint pjp, RequestMapping requestMapping) throws Throwable {
String authError = null;
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String decision = SecurityUtils.evaluatePolicy(request);
if(!(decision.toUpperCase().equals(SecurityUtils.PERMIT))) {
authError = decision + " : Request not permittted per policy.";
log.warn("Not permitted per policy. Returning without executing: " + authError);
Map<String,String> responseBody = new HashMap<>();
responseBody.put("path",request.getContextPath());
responseBody.put("message",authError);
return new ResponseEntity<>(responseBody,HttpStatus.OK);
}
return pjp.proceed();
}
}
当它在return new ResponseEntity<>(responseBody,HttpStatus.OK);
建议中执行@Around
时,它会第二次重新进入around方法。
我在正常流程中执行的实际方法上设置一个断点,它永远不会被命中。
似乎是这个ma.invoke方法(return ma.invoke(obj, args);
)在返回ResponseEntity时被点击,并且它再次启动回到around方法。
package java.lang.reflect;
...
...
public final class Method extends Executable {
...
...
@CallerSensitive
public Object invoke(Object obj, Object... args)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException
{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class<?> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor; // read volatile
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
}
答案 0 :(得分:1)
感谢您的帮助。我想通了......
第一次进入我的建议方法:
pjp =
(org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint)
execution(List com.myCompany.controller.ApplicationController.getApplications())
第二次进入方法(在我回复401回复后):
pjp =
(org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint)
execution(ResponseEntity org.springframework.boot.autoconfigure.web.BasicErrorController.error(HttpServletRequest))
我为我的方面添加了这个:
@Around("@annotation(requestMapping) && execution( * com.myCompany.controller..*.*(..))")
public Object around(ProceedingJoinPoint pjp, RequestMapping requestMapping) throws Throwable {
它只执行一次。