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 Sina.

Your request sounds a bit like ordering Mousse au Chocolat without chocolate in a restaurant. 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.

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
 
 
 

Back to the top