我有一个spring AOP Aspect类,它在每次调用服务时都会记录,我计划在日志中打印更多信息,这次每个请求都会有唯一的标识符,这个标识符存储在一个请求范围对象,直到服务返回。我尝试将请求对象注入@Aspect,但似乎效果不好。
如果只有一个建议,它一次调用我的服务,如果我添加更多的建议,它会给出错误。(问题的结尾)
@Aspect
public class LoggingAspect {
private Logger log = Logger.getLogger(getClass());
@Autowired
public RequestScopeObject params;
@Pointcut("within(net.company.dao..*)")
private void clDaoLayer() {
}
private String uniqueIdentifier(){
String uid = "";
if(this.params!=null && this.params.getId()!= null){
uid = "ID:"+this.params.getId()+" ";
}else{
uid = "";
}
return uid;
}
@Around("clDaoLayer()")
public Object clDaoLayerAdvice(ProceedingJoinPoint joinPoint)
throws Throwable {
String TAG = uniqueIdentifier();
// gets the system property dynamically for debugging purpose.
this.printObject = Boolean.parseBoolean(System.getProperty("printobject"));
Date start = new Date();
String methodInExcecuting = getSignature(joinPoint);
log.debug(TAG+"calling method.." + methodInExcecuting
+ " with arguments : " + Arrays.toString(joinPoint.getArgs()));
Object result = null;
String slug = "";
try {
result = joinPoint.proceed();
} catch (Exception e) {
log.error(TAG+" Exception .." + methodInExcecuting, e);
throw e;
}
try {
if (printObject == true) {
if (result == null) {
slug = " null ";
} else if (result instanceof List) {
slug = ((List) result).toString() + "\n"
+ ((List) result).size() + "";
} else if (result.getClass().toString().indexOf("[L") >= 0) {// if
// array
// get
// length
slug = ArrayUtils.toString(result) + ". "
+ ArrayUtils.getLength(result);
} else if (result != null) {
slug = result.toString() + ". 1 value ";
}
slug += "\nvalues/rows returned.";
} else {
slug = "";
}
} catch (Exception e) {
log.debug(TAG+"Error getting slug..");
}
Date end = new Date();
log.debug(TAG+" Time taken: "
+ (end.getTime() - start.getTime()) + " milliseconds."+"returning from " + methodInExcecuting + ". " + slug);
return result;
}
}
日志错误
java.lang.reflect.UndeclaredThrowableException
at org.jboss.ws.core.server.ServiceEndpointInvoker.invoke(ServiceEndpointInvoker.java:228)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.processRequest(RequestHandlerImpl.java:474)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.handleRequest(RequestHandlerImpl.java:295)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.doPost(RequestHandlerImpl.java:205)
at org.jboss.wsf.stack.jbws.RequestHandlerImpl.handleHttpRequest(RequestHandlerImpl.java:131)
at org.jboss.wsf.common.servlet.AbstractEndpointServlet.service(AbstractEndpointServlet.java:85)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126)
at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:829)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:598)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.StackOverflowError
at java.util.Date.<init>(Date.java:146)
at net.LoggingAspect.restClientHelperAdvice(LoggingAspect.java:134)
at sun.reflect.GeneratedMethodAccessor317.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy593.getId(Unknown Source)
答案 0 :(得分:1)
我使用ThreadLocal的帮助来维护我想要打印的信息。我已经使用静态变量来保存线程局部变量
public class WorkThreadLocal {
public static ThreadLocal<String> id = new ThreadLocal<String>(){
@Override
protected String initialValue()
{
return "";
}
};
}
更新的LogginAspect.java位于
之下@Aspect
public class LoggingAspect {
private Logger log = Logger.getLogger(getClass());
@Autowired
public RequestScopeObject params;
@Pointcut("within(net.company.dao..*)")
private void clDaoLayer() {
}
private String uniqueIdentifier(){
String uid = "";
if (WorkThreadLocal.mwi != null) {
uid = WorkThreadLocal.id.get() + " ";
}
return uid;
}
@Around("clDaoLayer()")
public Object clDaoLayerAdvice(ProceedingJoinPoint joinPoint)
throws Throwable {
String TAG = uniqueIdentifier();
// gets the system property dynamically for debugging purpose.
this.printObject = Boolean.parseBoolean(System.getProperty("printobject"));
Date start = new Date();
String methodInExcecuting = getSignature(joinPoint);
log.debug(TAG+"calling method.." + methodInExcecuting
+ " with arguments : " + Arrays.toString(joinPoint.getArgs()));
Object result = null;
String slug = "";
try {
result = joinPoint.proceed();
} catch (Exception e) {
log.error(TAG+" Exception .." + methodInExcecuting, e);
throw e;
}
try {
if (printObject == true) {
if (result == null) {
slug = " null ";
} else if (result instanceof List) {
slug = ((List) result).toString() + "\n"
+ ((List) result).size() + "";
} else if (result.getClass().toString().indexOf("[L") >= 0) {// if
// array
// get
// length
slug = ArrayUtils.toString(result) + ". "
+ ArrayUtils.getLength(result);
} else if (result != null) {
slug = result.toString() + ". 1 value ";
}
slug += "\nvalues/rows returned.";
} else {
slug = "";
}
} catch (Exception e) {
log.debug(TAG+"Error getting slug..");
}
Date end = new Date();
log.debug(TAG+" Time taken: "
+ (end.getTime() - start.getTime()) + " milliseconds."+"returning from " + methodInExcecuting + ". " + slug);
return result;
}
}
答案 1 :(得分:0)
我有同样的问题。我的解决方案是将数据存储在请求范围内的bean中,然后从应用程序上下文中懒惰地获取该bean:
@Aspect
public class PerformanceMonitoringAspect implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
private boolean isRequestScopeAvailable() {
return RequestContextHolder.getRequestAttributes() != null;
}
public Optional<QueryCounter> getQueryCounter() {
if (isRequestScopeAvailable()) {
return Optional.of(applicationContext.getBean(QueryCounter.class));
}
return Optional.empty();
}
@Before("@annotation(com.whatever.CountAsWriteQuery)")
public void countAsWriteQueries() {
getQueryCounter().ifPresent(QueryCounter::incrementWrite);
}
}
@RequestScope
public class QueryCounter {
public void incrementWrite(){
...
}
}