【发布时间】:2019-02-08 12:59:15
【问题描述】:
我是 Spring AOP 世界的新手。我正在尝试使用 AOP 构建 Spring Boot 日志记录。我在 MongoDB 中创建了一个名为“Audit report”的集合,它存储对象的旧值和更新值。我正在为此使用 Spring AOP 的 @Before 和 @After 注解。
假设我必须编辑该对象,因此应将其以前的名称和更新后的名称输入到数据库中。
这是我的审计报告课,
@Data
@Document(collection="auditReport")
public class AuditReport extends AuditEntity {
private String description;
private String old_value;
private String new_value;
}
这个id实体类,
public class AuditEntity {
@Field("createdDate")
@CreatedDate
private Date createdDate;
@Field("createdBy")
@CreatedBy
private String createdBy;
@Field("updatedDate")
@LastModifiedDate
private Date updatedDate;
@Field("updatedBy")
@LastModifiedBy
private String updatedBy;
@Field("version")
@Version
private Long version;
}
这是我的方面类,
@Before("execution(* com.controller.DeliveryMethodsController.edit*(..)) && target(instance) && args(deliveryMethodObject) ")
public void before(JoinPoint joinPoint,Object instance,DeliveryMethods deliveryMethodObject) throws Exception {
LOGGER.info("Entering inside Aspect "+ joinPoint.getSignature().getName());
Object[] signatureArgs = joinPoint.getArgs();
LOGGER.info("Input: ",signatureArgs.toString());
String methodName = joinPoint.getSignature().getName();
Object previous = instance.getClass().getMethod(methodName.replaceFirst("edit", "get")).invoke(deliveryMethodObject);
AuditReport report = new AuditReport();
String prop = joinPoint.getSignature().getName().substring(4);
Object target = joinPoint.getTarget();
Object before = target.getClass().getMethod("get" + prop).invoke(deliveryMethodObject);
Object now = joinPoint.getArgs()[0];
System.out.println(prop + " changed from " + before + " to " + now);
report.setDescription(joinPoint.getSignature().getName());
System.out.println("DM object "+deliveryMethodObject);
System.out.println(" report "+report);
audiRepo.save(report);
}
当我尝试编辑 DeliveryMethod 时,我正在使用 get 方法获取以前的记录,该方法具有相同的参数,即 Id。
但它给了我这样的错误,
java.lang.NoSuchMethodException: com.exelatech.printshop.controller.DeliveryMethodsController.getDeliveryMethodById()
at java.lang.Class.getMethod(Class.java:1778) ~[na:1.8.0_25]
at com.exelatech.printshop.auditDetails.PrintshopAspect.before(PrintshopAspect.java:67) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_25]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_25]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_25]
at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_25]
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:629) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:611) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.aop.aspectj.AspectJMethodBeforeAdvice.before(AspectJMethodBeforeAdvice.java:43) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:51) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:62) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673) ~[spring-aop-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at com.exelatech.printshop.controller.DeliveryMethodsController$$EnhancerBySpringCGLIB$$9478e58b.editDeliveryMethodById(<generated>) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_25]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_25]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_25]
at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_25]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:661) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) [tomcat-embed-websocket-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55) [spring-boot-1.5.6.RELEASE.jar:1.5.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at com.exelatech.printshop.SimpleCORSFilter.doFilter(SimpleCORSFilter.java:38) [classes/:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110) [spring-boot-actuator-1.5.6.RELEASE.jar:1.5.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106) [spring-boot-actuator-1.5.6.RELEASE.jar:1.5.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.16.jar:8.5.16]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.16.jar:8.5.16]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_25]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_25]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.16.jar:8.5.16]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_25]
这是我的控制器类,
@RestController
@RequestMapping(value="/deliveryMethods")
public class DeliveryMethodsController {
private static final Logger logger = LoggerFactory.getLogger(DeliveryMethodsController.class);
@Autowired
private DeliveryMethodService deliveryMethodService;
@Autowired
public DeliveryMethodsController(DeliveryMethodService deliveryMethodService){
super();
}
@RequestMapping(value = "/createDeliveryMethod", method = RequestMethod.POST, consumes = "application/json;charset=UTF-8",produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseEntityResponse<DeliveryMethods>> createDeliveryMethod(@RequestBody DeliveryMethods deliveryMethodObject) {
logger.debug("Entering inside create delivery Method", deliveryMethodObject);
return deliveryMethodService.createDeliveryMethod(deliveryMethodObject);
}
@RequestMapping(value = "/getActiveDeliveryMethod", method = RequestMethod.POST, consumes = "application/json;charset=UTF-8",produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseEntityResponse<DeliveryMethods>> getActiveDeliveryMethod(@RequestBody DeliveryMethods deliveryMethodObject) {
logger.debug("Entering inside getAll active delivery methods method", deliveryMethodObject);
return deliveryMethodService.getActiveDeliveryMethod(deliveryMethodObject);
}
@RequestMapping(value = "/getDeliveryMethod", method = RequestMethod.POST, consumes = "application/json;charset=UTF-8",produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseEntityResponse<DeliveryMethods>> getDeliveryMethod(@RequestBody DeliveryMethods deliveryMethodObject) {
logger.debug("Entering inside getAll delivery methods method", deliveryMethodObject);
return deliveryMethodService.getDeliveryMethod(deliveryMethodObject);
}
@RequestMapping(value = "/getDeliveryMethodById", method = RequestMethod.POST, consumes = "application/json;charset=UTF-8",produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseEntityResponse<DeliveryMethods>> getDeliveryMethodById(@RequestBody DeliveryMethods deliveryMethodObject) {
logger.debug("Entering inside get delivery methods by Id method", deliveryMethodObject);
return deliveryMethodService.getDeliveryMethodById (deliveryMethodObject);
}
@RequestMapping(value = "/editDeliveryMethodById", method = RequestMethod.POST, consumes = "application/json;charset=UTF-8",produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseEntityResponse<DeliveryMethods>> editDeliveryMethodById(@RequestBody DeliveryMethods deliveryMethodObject) {
logger.debug("Entering inside edit delivery methods by Id method", deliveryMethodObject);
return deliveryMethodService.editDeliveryMethodById (deliveryMethodObject);
}
@RequestMapping(value = "/deleteDeliveryMethod", method = RequestMethod.POST, consumes = "application/json;charset=UTF-8",produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseEntityResponse<DeliveryMethods>> deleteDeliveryMethod(@RequestBody DeliveryMethods deliveryMethodObject) {
logger.debug("Entering inside delete delivery methods by Id method", deliveryMethodObject);
return deliveryMethodService.deleteDeliveryMethod(deliveryMethodObject);
}
@RequestMapping(value = "/enableOrDisabledDeliveryMethod", method = RequestMethod.POST, consumes = "application/json;charset=UTF-8",produces = "application/json;charset=UTF-8")
public ResponseEntity<BaseEntityResponse<DeliveryMethods>> enableOrDisabledDeliveryMethod(@RequestBody DeliveryMethods deliveryMethodObject) {
logger.debug("Entering inside enable or disable delivery methods by Id method", deliveryMethodObject);
return deliveryMethodService.enableOrDisabledDeliveryMethod(deliveryMethodObject);
}
}
这是模型类,
public class DeliveryMethods extends AuditEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@Field("methodId")
private String methodId;
@Field("deliveryMethodName")
private String deliveryMethodName;
@Field("displayLabel")
private String displayLabel;
@Field("serviceType")
private String serviceType;
@Field("courierService")
private List<Object> courierService;
@Field("address")
private List<Object> address;
@Field("isActive")
private boolean isActive;
@Field("deliveryAddress")
private String deliveryAddress;
@Field("isDeleted")
private boolean isDeleted;
@Field("selectedIncart")
private boolean selectedIncart;
@Field("createdOn")
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime createdOn;
}
但是这个方法存在于我的控制器中。 谁能建议我解决这个问题?或者建议我在编辑对象时获取旧值的替代方法。 提前致谢。
【问题讨论】:
-
反射的东西看起来有点难看,但除此之外:我猜你的方法需要一个参数(ID),但你正在寻找一个没有参数的方法。如果有帮助,请告诉我,我会将评论转换为您可以接受的答案。
-
我已经将参数添加到方法中,例如 Object before = target.getClass().getMethod("get" + prop).invoke(deliveryMethodObject);你能告诉我传递参数的确切方法吗?
-
见Javadoc。我还没有执行你的代码,但我认为你应该写
.invoke(instance, deliveryMethodObject)。我没有检查您的代码中是否还有其他缺点。如果这不能解决您的问题,请告诉我,我可以将代码复制到我的 IDE 中并尝试运行它。 -
你好 Kriegaex,我已经尝试过了,但没有工作。我得到的仍然是“NoSuchMethodException”错误。你能帮帮我吗?。
-
当然,如果我能重现您的问题。但是在您的示例代码中,我没有看到大量的类和注释。所以请给我一个MCVE,我可以编译和运行它。特别是我需要查看课程
DeliveryMethodsController和DeliveryMethods,但是完整的MCVE 会好得多。我不想猜测您的代码可能是什么样子。如果您甚至不显示它,我怎么知道您要使用反射呢?
标签: spring-boot spring-aop spring-aspects