views:

254

answers:

2

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 {
    ...
}
+3  A: 

Hello,

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:

Illustrating pointcuts from inside the Eclipse AJDT plugin.

The aspect that will add a join point on the three methods with an orange arrow, 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.

Espen
It looks good, but it's not exactly what I'm looking for. I edited my question in order to be more accurate. Thanks.
Sinuhe
I've found a method for simplifying it. I edited my question, but all credits on you! Thanks.
Sinuhe
Good edit! Glad to see you like this kind of questions ;)
Sinuhe
Thanks! I wanted to make it more informal for my own part as well. The downside is that the post got converted automatically to a community wiki..
Espen
A: 

I'have quit the same problem :

The aspect class look like this

@Pointcut("execution(@MyAnnotationForMethod * *(..,@aspects.MyAnnotationForParam Object, ..)) && args(lang)")
void myPointcut(JoinPoint thisJoinPoint, Object obj) {
}

@Before("myPointcut(thisJoinPoint ,  lang)")
public void doStuffOnParam(JoinPoint thisJoinPoint, Object obj) {
    LOGGER.info("doStuffOnParam :"+obj);
}

The annoted method

@MyAnnotationForMethod
public string theMethod(String a, @MyAnnotationForParam @OtherAnnotation Object obj, Object b){ 
LOGGER.info(a+obj+b);
}

With eclipse -> warnings : On the poincut : Multiple markers at this line - no match for this type name: MyAnnotationForMethod [Xlint:invalidAbsoluteTypeName] - no match for this type name: aspects.MyAnnotationForParam On the before : advice defined in xxx.xxx.xxx.xxx.MyAspect has not been applied [Xlint:adviceDidNotMatch]

Using last aspectJ plugin from http://download.eclipse.org/tools/ajdt/35/update

With maven command line using aspectj 1.6.9 [WARNING] no match for this type name: MyAnnotationForMethod [Xlint:invalidAbsoluteTypeName] [WARNING] no match for this type name: aspects.MyAnnotationForParam [Xlint:invalidAbsoluteTypeName] [WARNING] advice defined in xxx.xxx.xxx.xxx.MyAspect has not been applied [Xlint:adviceDidNotMatch]

Can you tell me what is wrong ?

Patrick Sauts
I don't know what's wrong. It seems ok to me, but I'm not an expert in AOP. But if you post this as a new question a lot of people interested in AOP will see it. You can include a link to this question if you think is necessary.
Sinuhe
You should delete this as well. It's a question, not an answer. And you asked it here: http://stackoverflow.com/questions/3565718/pointcut-matching-methods-with-annotated-parameters
seanizer