我想实现Spring Aspect进行日志记录。我尝试了此实现:
记录方面:
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Enumeration;
@Aspect
@Component
public class LoggingAspect {
private static final String CONTROLLER_EXPRESION = "within(@org.springframework.stereotype.Controller *) && execution(* *.*(..))";
private static final Logger log = LoggerFactory.getLogger(LoggingAspect.class);
/**
* Before -> Any resource annotated with @Controller annotation and all method
* and function taking HttpServletRequest as first parameter.
*
* @param joinPoint
* @param request
*/
@Before(CONTROLLER_EXPRESION)
public void logBefore(JoinPoint joinPoint, HttpServletRequest request) {
log.debug("Entering in Method : {}", joinPoint.getSignature().getName());
log.debug("Class Name : {}", joinPoint.getSignature().getDeclaringTypeName());
log.debug("Arguments : {}", Arrays.toString(joinPoint.getArgs()));
log.debug("Target class : {}", joinPoint.getTarget().getClass().getName());
if (null != request) {
log.debug("Start Header Section of request ");
log.debug("Method Type : {}", request.getMethod());
Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = headerNames.nextElement().toString();
String headerValue = request.getHeader(headerName);
log.debug("Header Name: {} Header Value : {}", headerName, headerValue);
}
log.debug("Request Path info : {}", request.getServletPath());
log.debug("End Header Section of request ");
}
}
/**
* After -> All method within resource annotated with @Controller annotation.
*
* @param joinPoint
* @param result
*/
@AfterReturning(pointcut = CONTROLLER_EXPRESION, returning = "result")
public void logAfter(JoinPoint joinPoint, Object result) {
String returnValue = this.getValue(result);
log.debug("Method Return value : {}", returnValue);
}
/**
* After -> Any method within resource annotated with @Controller annotation and throws an exception ...Log it
* @param joinPoint
* @param exception
*/
@AfterThrowing(pointcut = CONTROLLER_EXPRESION, throwing = "exception")
public void logAfterThrowing(JoinPoint joinPoint, Throwable exception) {
log.error("An exception has been thrown in {} {}", joinPoint.getSignature().getName(), " ()");
log.error("Cause : {}", exception.getCause());
}
/**
* Around -> Any method within resource annotated with @Controller annotation.
* @param joinPoint
* @return
* @throws Throwable
*/
@Around(CONTROLLER_EXPRESION)
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
try {
String className = joinPoint.getSignature().getDeclaringTypeName();
String methodName = joinPoint.getSignature().getName();
Object result = joinPoint.proceed();
long elapsedTime = System.currentTimeMillis() - start;
log.debug("Method {}.{} () execution time : {} ms", className, methodName, elapsedTime);
return result;
} catch (IllegalArgumentException e) {
log.error("Illegal argument {} in {}()", Arrays.toString(joinPoint.getArgs()), joinPoint.getSignature().getName());
throw e;
}
}
private String getValue(Object result) {
String returnValue = null;
if (null != result) {
if (result.toString().endsWith("@" + Integer.toHexString(result.hashCode()))) {
returnValue = ReflectionToStringBuilder.toString(result);
} else {
returnValue = result.toString();
}
}
return returnValue;
}
}
但是当我在应用服务器上部署代码时,我得到了这个错误堆栈:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration': Initialization of bean failed; nested exception is java.lang.IllegalArgumentException: error at ::0 formal unbound in pointcut
我要监视的控制器位于org.rest.api.server.controller.Homecontroller
-Java方法句柄下。我需要指定确切的路径还是遗漏其他内容?
答案 0 :(得分:0)
您的问题是由于HttpServletRequest
中的额外参数logBefore
引起的;方面无法绑定的。如果需要连接点的参数;最好在方面进行检查。因此,您的logBefore
方法应更改为:
@Before(CONTROLLER_EXPRESION)
public void logBefore(JoinPoint joinPoint, HttpServletRequest request) {
// ASPECT LOGIC
// ...
}
对此:
@Before(CONTROLLER_EXPRESION)
public void logBefore(JoinPoint joinPoint) {
HttpServletRequest request = (HttpServletRequest)joinPoint.getArgs()[0];
// ASPECT LOGIC
// ...
}
希望这会有所帮助。