Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AspectJ - change value of method parameter

I would like to have something like this:

public void doSomething(@ReplaceFooBar String myString) {
    //...
}

ReplaceFooBar is my custom annotation which should take the value of myString and do a replaceAll of "foo" with "bar" on it before the method starts executing so that it executes with the new string value. So, if the method was invoked with the parameter "I'm at the foo." it should actually execute with "I'm at the bar."

I don't know how to make this work. I've been fiddling with this for some time now. Let's say I last ended up at this point:

@Documented
@Target({ElementType.PARAMETER, ElementType.FIELD, ElementType.LOCAL_VARIABLE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ReplaceFooBar {
}

And...

@Aspect
public aspect ReplaceFooBarAspect {
    @Before("@annotation(ReplaceFooBar)")
    public String replaceFooBar(String value) {
        if (value == null) {
            return null;
        }
        return value.replaceAll("foo", "bar");
    }
}

What am I doing wrong?

My code isn't compiling, I'm getting errors like these.

Error:(6, 0) ajc: Duplicate annotation @Aspect
Error:(7, 0) ajc: aspects cannot have @Aspect annotation
Error:(10, 0) ajc: This advice must return void
Error:(10, 0) ajc: formal unbound in pointcut

I don't know how these aspects work exactly, how to get this working the way I want it.

like image 786
morgoth84 Avatar asked Aug 14 '17 11:08

morgoth84


1 Answers

To execute method with different argument you should use @Around advice and replace arguments manually in code.

For example:

@Around("execution(* *(.., @aspectjtest.ReplaceFooBar (*), ..))")
public Object replaceFooBar(ProceedingJoinPoint pjp) throws Throwable {
    //get original args
    Object[] args = pjp.getArgs();

    //get all annotations for arguments
    MethodSignature signature = (MethodSignature) pjp.getSignature();
    String methodName = signature.getMethod().getName();
    Class<?>[] parameterTypes = signature.getMethod().getParameterTypes();
    Annotation[][] annotations;
    try {
        annotations = pjp.getTarget().getClass().
                getMethod(methodName, parameterTypes).getParameterAnnotations();
    } catch (Exception e) {
        throw new SoftException(e);
    }

    //Find annotated argument
    for (int i = 0; i < args.length; i++) {
        for (Annotation annotation : annotations[i]) {
            if (annotation.annotationType() == ReplaceFooBar.class) {
                Object raw = args[i];
                if (raw instanceof String) {
                    // and replace it with a new value
                    args[i] = ((String) raw).replaceAll("foo", "bar");
                }
            }
        }
    }
    //execute original method with new args
    return pjp.proceed(args);
}
like image 108
Vlad Bochenin Avatar answered Oct 14 '22 14:10

Vlad Bochenin