【问题标题】:Intercepting method with Spring AOP using only annotations仅使用注释的 Spring AOP 拦截方法
【发布时间】:2010-04-10 02:18:14
【问题描述】:

在我的 Spring 上下文文件中,我有这样的内容:

<bean id="userCheck" class="a.b.c.UserExistsCheck"/>
<aop:config>
      <aop:aspect ref="userCheck">
         <aop:pointcut id="checkUser"
                expression="execution(* a.b.c.d.*.*(..)) &amp;&amp; args(a.b.c.d.RequestObject)"/>
         <aop:around pointcut-ref="checkUser" method="checkUser"/>
      </aop:aspect>
</aop:config>    

a.b.c.UserExistsCheck 如下所示:

@Aspect
public class UserExistsCheck {

@Autowired
private UserInformation userInformation;

public Object checkUser(ProceedingJoinPoint pjp) throws Throwable {
    int userId = ... //get it from the RequestObject passed as a parameter
    if (userExists(userId)) {
        return pjp.proceed();
    } else {
        return new ResponseObject("Invalid user);
    }
}

被这些东西拦截的类看起来像这样:

public class Klazz {
    public ResponseObject doSomething(RequestObject request) {...}
}

这行得通。在将调用传递给 Klazz 之前,根据需要执行 UserExistCheck。问题是这是我让它工作的唯一方法。通过使用注释而不是上下文文件来完成这项工作,对于我的小脑袋来说似乎太多了。那么......我究竟应该如何注释 UserExistsCheck 和 Klazz 中的方法?我还需要别的东西吗?另一个班级?上下文文件中还有内容吗?

【问题讨论】:

    标签: java spring annotations spring-aop


    【解决方案1】:

    您是否启用了基于注释的 AOP? documentation 说你必须添加

    <aop:aspectj-autoproxy/>
    

    到您的弹簧配置。然后你需要在你的checkUser 方法前面添加一个注解。看起来您想要@Around 建议,如here 所述。

    @Aspect
    public class UserExistsCheck {
    
      @Around("execution(* a.b.c.d.*.*(..)) && args(a.b.c.d.RequestObject)")
      public Object checkUser(ProceedingJoinPoint pjp) throws Throwable {
    

    【讨论】:

    • 是的,我从一开始就启用了。我也试过这个,但没有用,checkUser 方法永远不会被调用:(
    • 其实这确实工作,我只是在args中犯了一个愚蠢的错误,谢谢!现在我想知道在尝试上下文文件方法之前我最初做错了什么......
    【解决方案2】:

    从您提供的示例代码看来,您正在尝试为未实现任何接口的类创建建议。如 Spring 文档的 Proxying Mechanisms 部分所述,如果要执行此操作,则需要启用 CGLIB:

    <aop:aspectj-autoproxy proxy-target-class="true" />
    

    我个人发现这比文档中显示的更挑剔,虽然如果所有的星星都正确对齐,它确实有效,但从设计的角度来看,它通常更容易——而且更可取—— - 在接口上声明您的 AOP 建议,如下所示。 (请注意,您需要从您的 BeanFactory/ApplicationContext 获取您的 KlazzImpl 实例。)

    public interface Klazz {
      ResponseObject doSomething(RequestObject request);
    }
    
    public class KlazzImpl implements Klazz {
      public ResponseObject doSomething(RequestObject request) {...}
    }
    

    此外,您对args 表达式的使用有点偏离。请参阅以下内容:

    @Aspect
    public class UserExistsCheck {
      @Autowired
      private UserInformation userInformation;
    
      @Around("execution(* a.b.c.d.*.*(..)) && args(reqObj)")
      public Object checkUser(ProceedingJoinPoint pjp, a.b.c.d.RequestObject reqObj) throws Throwable {
          // ...
      }
    }
    

    这些更改应该可以完成工作。

    【讨论】:

    • 感谢您的提示,实际上 Klazz 确实实现了一个接口,但我使用 Spring 自动装配来创建实例。很抱歉没有告知这一点,我认为这无关紧要。无论如何,所有信息都很有用,谢谢!
    【解决方案3】:

    自春季 3.1 起,将 @EnableAspectJAutoProxy(proxyTargetClass=true) 添加到您的 @Configuraiton

    【讨论】:

      猜你喜欢
      • 2019-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-07
      • 1970-01-01
      • 2013-08-10
      • 2012-01-12
      • 1970-01-01
      相关资源
      最近更新 更多