带注释参数的切入点匹配方法

发布于 2024-08-30 23:18:53 字数 819 浏览 2 评论 0原文

我需要创建一个切入点与方法匹配的切面,如果:

  • 是 public
  • 它的类用 @Controller 注释(最后没有)
  • 它的参数之一(可以有许多) 用@MyParamAnnotation 进行注释。

我认为前两个条件很容易,但我不知道用Spring是否可以完成第三个条件。如果不是,也许我可以将其更改为:

  • 它的参数之一是 com.me.MyType 类型的实例(或实现某些接口)

您认为可以实现这一目标吗?而且性能会好吗?

谢谢

编辑:匹配方法的一个示例。正如您所看到的,MyMethod 没有带注释(但可以带注释)。

@Controller
public class MyClass {
    public void MyMethod (String arg0, @MyParamAnnotation Object arg1, Long arg3) {
        ...
    }
}

编辑:我最终使用的解决方案基于@Espen 的答案。正如你所看到的,我稍微改变了我的条件:类实际上不需要是@Controller。

@Around("execution(public * * (.., @SessionInject (*), ..))")
public void methodAround(JoinPoint joinPoint) throws Exception {
    ...
}

I need to create an aspect with a pointcut matching a method if:

  • Is public
  • Its class is annotated with @Controller (Finally does not)
  • One of its parameters (can have many) is annotated with @MyParamAnnotation.

I think the first two conditions are easy, but I don't know if its possible to accomplish the third with Spring. If it is not, maybe I can change it into:

  • One of its parameters is an instance of type com.me.MyType (or implements some interface)

Do you think it's possible to achieve this? And will performance be good?

Thanks

EDIT: One example of a matching method. As you can see, MyMethod is not annotated (but it can be).

@Controller
public class MyClass {
    public void MyMethod (String arg0, @MyParamAnnotation Object arg1, Long arg3) {
        ...
    }
}

EDIT: The solution I finally used, based on @Espen answers. As you can see, I changed my conditions a little: class doesn't actually need to be a @Controller.

@Around("execution(public * * (.., @SessionInject (*), ..))")
public void methodAround(JoinPoint joinPoint) throws Exception {
    ...
}

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

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

发布评论

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

评论(1

不忘初心 2024-09-06 23:18:53

这是一个有趣的问题,所以我创建了一个小示例应用程序来解决这个问题! (随后根据 Sinuhe 的反馈对其进行了改进。)

我创建了一个 DemoController 类,该类应该作为方面的示例:

@Controller
public class DemoController {

    public void soSomething(String s, @MyParamAnnotation Double d, Integer i) {
    }

    public void doSomething(String s, long l, @MyParamAnnotation int i) {
    }

    public void doSomething(@MyParamAnnotation String s) {
    }

    public void doSomething(long l) {
    }
}

该方面将在前三个方法上添加连接点,但不会在最后一个方法,其中参数未使用 @MyParamAnnotation 进行注释:

@Aspect
public class ParameterAspect {

    @Pointcut("within(@org.springframework.stereotype.Controller *)")
    public void beanAnnotatedWithAtController() {
    }

    @Pointcut("execution(public * *(.., @aspects.MyParamAnnotation (*), ..))")
    public void methodWithAnnotationOnAtLeastOneParameter() {
    }

    @Before("beanAnnotatedWithAtController() " 
            + "&& methodWithAnnotationOnAtLeastOneParameter()")
    public void beforeMethod() {    
        System.out.println("At least one of the parameters are " 
                  + "annotated with @MyParamAnnotation");
    }
}

第一个切入点将在标有 @Controller 的类内的所有方法上创建连接点。

当满足以下条件时,第二个切入点将添加一个连接点:

  • 公共方法
  • 第一个 * 是每个返回类型的通配符。
  • 第二个 * 是所有类中所有方法的通配符。
  • (.., 匹配带注释的参数之前的零到多个任意类型的参数。
  • @aspects.MyParamAnnotation (*), 匹配使用给定注释注释的参数。
  • ..) 匹配带注释的参数后面的零到多个任何类型的参数。

最后,@Before 建议建议满足两个切入点中所有条件的所有方法。

该切入点适用于 AspectJ 和 Spring AOP!

当谈到性能时。开销很小,特别是使用在编译时或加载时进行编织的 AspectJ。

It was an interesting problem, so I created a little sample application to solve the case! (And improved it with Sinuhe's feedback afterwards.)

I have created a DemoController class that should work as an example for the aspect:

@Controller
public class DemoController {

    public void soSomething(String s, @MyParamAnnotation Double d, Integer i) {
    }

    public void doSomething(String s, long l, @MyParamAnnotation int i) {
    }

    public void doSomething(@MyParamAnnotation String s) {
    }

    public void doSomething(long l) {
    }
}

The aspect that will add a join point on the first three methods, but not the last method where the parameter isn't annotated with @MyParamAnnotation:

@Aspect
public class ParameterAspect {

    @Pointcut("within(@org.springframework.stereotype.Controller *)")
    public void beanAnnotatedWithAtController() {
    }

    @Pointcut("execution(public * *(.., @aspects.MyParamAnnotation (*), ..))")
    public void methodWithAnnotationOnAtLeastOneParameter() {
    }

    @Before("beanAnnotatedWithAtController() " 
            + "&& methodWithAnnotationOnAtLeastOneParameter()")
    public void beforeMethod() {    
        System.out.println("At least one of the parameters are " 
                  + "annotated with @MyParamAnnotation");
    }
}

The first pointcut will create a joinpoint on all methods inside classes marked with @Controller.

The second pointcut will add a joinpoint when the following conditions are met:

  • public method
  • first * is a wildcard for every return type.
  • second * is a wildcard for all methods in all classes.
  • (.., matches zero to many parameters of any type before the annotated parameter.
  • @aspects.MyParamAnnotation (*), matches a parameter annotated with the given annotation.
  • ..) matches zero to many parameters of any type after the annotated parameter.

Finally, the @Before advice advises all methods where all conditions in both pointcuts are satisfied.

The pointcut works with both AspectJ and Spring AOP!

When it comes to performance. The overhead is small, especially with AspectJ that does the weaving on compile-time or load-time.

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