【问题标题】:AspectJ with Spring : intercepted methods lose their parameters annotations带有 Spring 的 AspectJ:被截获的方法会丢失其参数注释
【发布时间】:2018-03-12 02:30:49
【问题描述】:

我最近在我现有的 spring 项目中添加了带有 aspectJ 和 spring-aop 的 AOP。目标是实际拦截控制器调用以修改它们发回的响应,以便将一些值绑定到此响应我不想手动添加到我的每个控制器,例如实际令牌的到期日期最终用户使用(无论如何我都无法在我的控制器中展示)。在我开始单元测试之前,我实际上设法让它工作:

在我的单元测试中,我使用 java 中的反射功能直接调用我的控制器方法,然后复制通常的过程(调用过滤器链、预处理程序和后处理程序,以及控制器方法本身,它首先在注释时使用 spring 验证器手动验证@Valid 出现在我的一个参数上。所有这些过程都可以正常工作并正确执行)。问题是现在控制器方法被spring-aop拦截了,它被提到来自创建的代理控制器,并且我所有的参数注释都消失了。这是一个控制器示例:

@Override
public ResponseEntity<Object> editPassword(@Valid @RequestBody PasswordEditForm passwordEditForm, HttpServletRequest request) {
    return factorizedUserBaseController.editPassword(passwordEditForm, request, User.class);
}

参数 PasswordEditForm 有注释 @Valid 所以在我的测试用例中,它在任何其他步骤之前首先被验证,但现在当我仔细检查它时,代理方法上不存在 @Valid 注释,因此参数不'没有得到验证,关于如何解决这个问题并使我的参数注释从我的测试角度仍然可以理解的任何线索?

注意:当通过 mvn spring-boot:run 运行 spring 时,带有 @Valid 注释的参数得到正确验证,然后正确地转到我的错误处理程序方法。

【问题讨论】:

    标签: java annotations aspectj spring-aop


    【解决方案1】:

    问题已解决:从其他几篇 stackoverflow 帖子中,我了解到 CGLIB(Spring 使用的 aop 代理库)不支持注释。 (见Retain annotations on CGLIB proxies?)。但是我的问题不在这里,我从字面上确定我正在使用控制器类本身(我编码的那个)找到方法,但我错的是我将控制器实例作为参数提供给了其他部分我的代码反过来会使用这个控制器类来找到当然不工作的方法,因为多亏了 Spring 代理,它不再是我的控制器本身,而是一个扩展我自己的控制器类的代理类。相反,我只需要替换:

        Class<?> controllerClass = controllerInstanciationContainer
                .getController()
                .getClass();
    

        Class<?> controllerClass = controllerInstanciationContainer
                .getController()
                .getClass()
                .getSuperclass();
    

    【讨论】:

    • 我建议你全力以赴并使用 AspectJ 而不是 Spring AOP。 Spring AOP 及其基于代理的解决方案的能力远不如直接操作 AspectJ 的字节码。
    • 我不知道甚至可以将 Spring 与 all-in AspectJ 一起使用!我认为这是不可能的,这就是 Spring 开发它的 spring-aop 库的原因。感谢您的评论,我会看看这种可能性,因为在查看堆栈跟踪时,我印象深刻的是,执行这一小段字节码需要多少步骤......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多