Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Getting the method arguments of a Pointcut using args

Hi Alexander, 

Thanks for response. Please find my comments below.

On Sep 5, 2019, at 5:30 AM, Alexander Kriegisch <alexander@xxxxxxxxxxxxxx> wrote:

Hi Sina.

Your request sounds a bit like ordering Mousse au Chocolat without chocolate in a restaurant.

Interesting metaphor but I don’t see it being the case here :) 

Your advice has two very specific Foo and Bar parameters, but the corresponding pointcut should not bind them to method parameters. Where else would they come from then? What is the problem anyway? Please give me a reason for wishing to avoid making the pointcut specific to the method signature, then maybe I can help you find a solution for your problem.



The idea is to be able to annotate a method to tag it so that you can define an Aspect in which you extract some information from the annotation and the annotated method, hence @CallerAnnotation * *(..)).  The reason that I’m using * * (..) is because the I don’t want the Aspect to become aware of signature of the annotated method as this won’t scale if I’m going to use the annotation on top of different methods with different signatures. 

If I have to bind the the Pointcut definition to a specific method signature then I’m losing the generalization that I get through the annotation. If I only had one PointCut and my final JoinPoint was the annotated method then I could have easily used the thisJoinPoint.getArgs() in order to get the method arguments but since I’m using cflowbelow and combining that Pointcut with another Pointcut to catch the JoinPoint of the callee() method I can only access the args()  of the callee method but not the annotated method. 

I’m afraid that this is not possible only using AspectJ. My expectation was to be able to get an Object[] which contains the arguments of the annotated method without the need to specify its signature. 
One way that I can think of would be to have two different advices one for the annotated method and another one for the callee method and use ThreadLocal to pass on the information (arguments of annotated method) and examine and read those args in the second advice from ThreadLocal.

Thanks.  

Just guessing you want to re-use the method execution pointcut for another advice, but this time more generically without specific parameters, you can just do it like this (full MCVE follows):

 

package de.scrum_master.app;

public class Foo {}



package de.scrum_master.app;

public class Bar {}



package de.scrum_master.app;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(METHOD)
public @interface CallerAnnotation {
String value();
}



package de.scrum_master.app;

public class SampleClazz {
@CallerAnnotation("xyz")
public void caller(Foo foo, Bar bar) {
callee("x", 11);
}

@CallerAnnotation("abc")
public void anotherCaller(int number) {
callee("y", number);
}

public void callee(String s, Integer i) {}

public static void main(String[] args) {
SampleClazz sampleClazz = new SampleClazz();
sampleClazz.caller(new Foo(), new Bar());
sampleClazz.anotherCaller(22);
}
}



package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

import de.scrum_master.app.Bar;
import de.scrum_master.app.CallerAnnotation;
import de.scrum_master.app.Foo;

@Aspect
public class MyAspect {
@Pointcut("execution(* *(..)) && @annotation(callerAnnotation)")
protected void executeAnnotation(CallerAnnotation callerAnnotation) {}

@Pointcut("executeAnnotation(callerAnnotation) && args(foo, bar)")
protected void executeAnnotationWithArgs(CallerAnnotation callerAnnotation, Foo foo, Bar bar) {}

@Pointcut("cflowbelow(executeAnnotation(callerAnnotation))")
protected void executeBelowAnnotation(CallerAnnotation callerAnnotation) {}

@Pointcut("cflowbelow(executeAnnotationWithArgs(callerAnnotation, foo, bar))")
protected void executeBelowAnnotationWithArgs(CallerAnnotation callerAnnotation, Foo foo, Bar bar) {}

@Pointcut(value = "execution(public void callee(String, Integer))")
protected void executeCallee() {}

@Around("executeCallee() && executeBelowAnnotationWithArgs(callerAnnotation, foo, bar)")
public Object finalAdvice(ProceedingJoinPoint joinPoint, CallerAnnotation callerAnnotation, Foo foo, Bar bar) throws Throwable {
System.out.println("[finalAdvice] " + joinPoint);
System.out.println(" " + callerAnnotation);
System.out.println(" " + foo);
System.out.println(" " + bar);
return joinPoint.proceed();
}

@Before("executeCallee() && executeBelowAnnotation(callerAnnotation)")
public void anotherAdvice(JoinPoint joinPoint, CallerAnnotation callerAnnotation) throws Throwable {
System.out.println("[anotherAdvice] " + joinPoint);
System.out.println(" " + callerAnnotation);
}
}
 
See how executeAnnotation(callerAnnotation) is re-used? Maybe this is what you want, maybe not, I have no idea.
 
BTW, the console log looks like this:
 
[finalAdvice] execution(void de.scrum_master.app.SampleClazz.callee(String, Integer))
@de.scrum_master.app.CallerAnnotation(value="xyz")
de.scrum_master.app.Foo@370736d9
de.scrum_master.app.Bar@5f9d02cb
[anotherAdvice] execution(void de.scrum_master.app.SampleClazz.callee(String, Integer))
@de.scrum_master.app.CallerAnnotation(value="xyz")
[anotherAdvice] execution(void de.scrum_master.app.SampleClazz.callee(String, Integer))
@de.scrum_master.app.CallerAnnotation(value="abc")
 
Regards
-- 
Alexander Kriegisch
https://scrum-master.de
 

Sina Golesorkhi schrieb am 05.09.2019 01:45:

Hi there I have the following code sample 
 
@Aspect
public class MyAspect {
 
    @Pointcut("cflowbelow(execution(@CallerAnnotation * *(..)) && @annotation(callerAnnotation))")
    protected void executeBelowAnnotation(final CallerAnnotation callerAnnotation) {
    }
 
    @Pointcut(value = "execution(public void callee(String, Integer))")
    protected void executeCallee() {
    }
 
    @Around("executeCallee() && executeBelowAnnotation(callerAnnotation)")
    public Object finalAdvice(final ProceedingJoinPoint joinPointfinal CallerAnnotation callerAnnotation)
            throws Throwable {
        return joinPoint.proceed();
    }
}
 
 
public class SampleClazz() {
 
    @CallerAnnotation("xyz")
    public void caller(Foo foo, Bar bar){
        this.callee();
    }
 
    private void callee(String s, Integer i){
      // Do Something
    }
}
 
and I would like to know is there any possibility to use the args such as args(..) in order to get the method arguments of the caller method in the following example?
 
I know that I can in my first pointcut define 
 
@Pointcut("cflowbelow(call(@CallerAnnotation * *(..)) && @annotation(callerAnnotation) && args(foo, bar))")
    protected void executeBelowAnnotation(final CallerAnnotation callerAnnotation, Foo foo, Bar bar) {
    }
 
So that I also pass on those method params to the finalAdvice method, however I would like to do this without explicitly defining the arguments in my pointcut so that it doesn’t depend on the signature of the annotated method. 
 
One way that I have done before has been using another annotation to annotate the params and then having @annotation in my pointcut but I would like to see whether I can skip having yet another annotation for this. 
 
Also another way might be the use of executionAdvice and then defining two advices and combining them together for the two pointcuts. That way I guess I can use the getMethodArgs() from ProceedingJoinPoint.
 
So is there any way to use the args() to achieve this? 
 
Regards
Sina
 
 
 
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://www.eclipse.org/mailman/listinfo/aspectj-users


Back to the top