如何解决如果在 sprig 启动项目中添加了 @EnableTransactionManagement,则 @Aspectj 日志记录会出现问题
我尝试使用 @Aspect
来记录所有请求和响应,代码运行良好且成功,具有通用配置且没有任何初始化的简单 spring boot
项目方法或数据库调用。
以下代码不起作用,其中包括对使用的所需数据的初始化配置和数据库调用 @EnableTransactionManagement
在运行我的应用程序时使用 @Aspect
时出现错误
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class MyContextClass implements ApplicationListener<ContextRefreshedEvent>{
@Autowire
private MyServiceRepository myServiceRepo;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// Added Db call
CommonUtils.setYears(myServiceRepo.getTotalYears());
}
}
@Aspect 日志代码
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
@Aspect
@Component
public class LoggingAspect {
private final Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
private HttpServletRequest request;
@Autowired
private HttpServletResponse response;
@pointcut("within(@org.springframework.stereotype.Repository *)"
+ " || within(@org.springframework.stereotype.Service *)"
+ " || within(@org.springframework.web.bind.annotation.RestController *)")
public void springBeanpointcut() {
// Method is empty as this is just a pointcut,the implementations are in the
// advices.
log.info("springBeanpointcut");
}
/**
* pointcut that matches all Spring beans in the application's main packages.
*/
@pointcut("within(com.test.mypackage..*)")
public void applicationPackagepointcut() {
// Method is empty as this is just a pointcut,the implementations are in the
// advices.
log.info("applicationPackagepointcut");
}
@Around("applicationPackagepointcut() && springBeanpointcut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
String className = methodSignature.getDeclaringType().getSimpleName();
String methodName = methodSignature.getName();
String methodParameterNames = methodSignature.getmethod().toString();
if (request ! = null) {
log.info(request.getRequestURL());
log.info(request.getmethod());
}
if (response != null) {
log.info(response.getRequestURL());
log.info(response.getStatus());
}
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object result = joinPoint.proceed();
stopWatch.stop();
}
此代码构建成功。但是当我运行下面的应用程序时,错误显示 setYears
中的错误2021-05-07 20:14:58 [restartedMain] ERROR o.s.boot.SpringApplication-[SpringApplication.java:856]-Application run Failed
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request,or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message,your code is probably running outside of dispatcherServlet: In this case,use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)
at org.springframework.web.context.support.WebApplicationContextUtils.currentRequestAttributes(WebApplicationContextUtils.java:313)
at org.springframework.web.context.support.WebApplicationContextUtils.access$400(WebApplicationContextUtils.java:66)
at org.springframework.web.context.support.WebApplicationContextUtils$RequestObjectFactory.getobject(WebApplicationContextUtils.java:329)
at org.springframework.web.context.support.WebApplicationContextUtils$RequestObjectFactory.getobject(WebApplicationContextUtils.java:324)
at org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler.invoke(AutowireUtils.java:292)
at com.sun.proxy.$Proxy120.getRequestURL(UnkNown Source)
at com.opl.ans.config.utils.LoggingAspect.logAround(LoggingAspect.java:137)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.cglibAopProxy$cglibMethodInvocation.proceed(cglibAopProxy.java:749)
at org.springframework.aop.framework.cglibAopProxy$DynamicAdvisedInterceptor.intercept(cglibAopProxy.java:691)
这是正确的做法吗?有什么建议吗?请帮忙。
解决方法
根据错误堆栈,问题是 request
实例无效。我猜想自动连接到 request
的 Aspect
实例可能已经过时,或者不与当前线程相关联。这意味着 request
实例不为空,并且 logAround()
方法中的检查给出了意想不到的结果。
RequestContextHolder.getRequestAttributes() 将返回 null
。修改
if (request ! = null) { ..}
与 if (RequestContextHolder.getRequestAttributes() ! = null) {..}
核对应该可以解决问题。
此外,spring boot 还为您当前通过 AOP 尝试的内容提供了开箱即用的解决方案。也请检查一下。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。