仅使用注释使用 Spring AOP 拦截方法

发布于 2024-08-28 12:18:45 字数 1201 浏览 8 评论 0原文

在我的 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>    

abcUserExistsCheck 看起来像这样:

@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) {...}
}

这有效。 UserExistCheck 在调用传递给 Klazz 之前根据需要执行。问题是这是我让它工作的唯一方法。通过使用注释而不是上下文文件来完成这项工作对于我的小大脑来说似乎太多了。那么...我到底应该如何注释 UserExistsCheck 和 Klazz 中的方法呢?我还需要其他东西吗?又一堂课?上下文文件中还有什么东西吗?

In my Spring context file I have something like this:

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

a.b.c.UserExistsCheck looks like this:

@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);
    }
}

And the class that is being intercepted with this stuff looks like this:

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

This works. UserExistCheck is executed as desired before the call is passed to Klazz. The problem is that this is the only way I got it working. To get this working by using annotations instead of the context file seems to be just too much for my small brain. So... how exactly should I annotate the methods in UserExistsCheck and Klazz? And do I still need something else too? Another class? Still something in the context file?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

源来凯始玺欢你 2024-09-04 12:18:45

您启用了基于注释的 AOP 吗? 文档< /a> 表示您必须添加

<aop:aspectj-autoproxy/>

到您的 spring 配置中。然后您需要在 checkUser 方法前面添加注释。看起来您需要 @Around 建议,如所述 此处

@Aspect
public class UserExistsCheck {

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

Have you enabled annotation-based AOP? The documentation says you have to add

<aop:aspectj-autoproxy/>

to your spring configuration. Then you need to add an annotation in front of your checkUser method. It looks like you want @Around advice, as described here.

@Aspect
public class UserExistsCheck {

  @Around("execution(* a.b.c.d.*.*(..)) && args(a.b.c.d.RequestObject)")
  public Object checkUser(ProceedingJoinPoint pjp) throws Throwable {
雄赳赳气昂昂 2024-09-04 12:18:45

从您提供的示例代码来看,您似乎正在尝试为未实现任何接口的类创建建议。如代理机制中所述Spring 文档的部分,如果您要执行此操作,则需要启用 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 {
      // ...
  }
}

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

From the example code you've provided, it appears that you're trying to create advice for a class that doesn't implement any interfaces. As described in the Proxying Mechanisms section of the Spring docs, if you're going to do this, you'll need to enable CGLIB:

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

I've personally found this to be a bit more finicky than the documentation indicates it should be, and though it does work if all of the stars are aligned just right, it's often easier--and preferable from a design standpoint--to declare your AOP advice on an interface, as follows. (Note that you'll need to obtain your instance of KlazzImpl from your BeanFactory/ApplicationContext.)

public interface Klazz {
  ResponseObject doSomething(RequestObject request);
}

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

Additionally, your use of the args expression is a little bit off. See the following:

@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 {
      // ...
  }
}

These changes should do the job.

不甘平庸 2024-09-04 12:18:45

从 spring 3.1 开始,将 @EnableAspectJAutoProxy(proxyTargetClass=true) 添加到您的 @Configuraiton

since spring 3.1 add @EnableAspectJAutoProxy(proxyTargetClass=true) to your @Configuraiton

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文