Annotation:
package de.scrum_master.app;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.FIELD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DynamicValue {
String lookupName() default "";
}
Driver application with an annotated member:
package de.scrum_master.app;
public class Application {
@DynamicValue(lookupName = "foobar")
public String greet;
public String anotherMember;
public static void main(String[] args) {
Application application = new Application();
application.greet = "world";
application.anotherMember = "Another member";
application.sayHello();
}
private void sayHello() {
System.out.println(anotherMember);
System.out.println("Hello " + greet);
}
}
Aspect:
package de.scrum_master.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.stereotype.Component;
import de.scrum_master.app.DynamicValue;
@Aspect
@Configurable
@Component
public class DynamicValueAspect {
@Pointcut("get(String de.scrum_master.app..*) && @annotation(dynamicValue)")
public void isDynamicValue(DynamicValue dynamicValue) {}
@Around("isDynamicValue(dynamicValue)")
public Object getLocalized(DynamicValue dynamicValue, ProceedingJoinPoint thisJoinPoint) throws Throwable {
System.out.println(thisJoinPoint);
System.out.println(" " + dynamicValue);
return thisJoinPoint.proceed();
}
}
Console log:
Another member
get(String de.scrum_master.app.Application.greet)
@de.scrum_master.app.DynamicValue(lookupName=foobar)
Hello world
By the way, a @Before
advice is sufficient if you do not want to change the result for get()
. For just printing something @Around
is overkill.
Because OP asked if it is possible to limit pointcut matching to a certain primitive type like int
, both capturing real primitives and the boxed type Integer
, I am going to show a variant doing just that. As as I said earlier, if there is not need to manipulate the value returned by the field accessor pointcut, there is no need to use @Around
either. We just use @AfterReturning
because it has an optional returning
parameter by means of which we can bind the actual return value to an advice parameter. If then we choose something other than Object
for that advice parameter - in this case we just use int
- we get what was asked for.
So let us add two annotated parameters typed int
and Integer
to the original code:
Driver application with annotated members:
package de.scrum_master.app;
public class Application {
@DynamicValue(lookupName = "foobar")
public String greet;
public String anotherMember;
@DynamicValue(lookupName = "primitive")
public int primitiveNumber;
@DynamicValue(lookupName = "boxed")
public Integer boxedNumber;
public static void main(String[] args) {
Application application = new Application();
application.greet = "world";
application.anotherMember = "Another member";
application.primitiveNumber = 11;
application.boxedNumber = 22;
application.sayHello();
}
private void sayHello() {
System.out.println(anotherMember);
System.out.println("Hello " + greet);
System.out.println(primitiveNumber);
System.out.println(boxedNumber);
}
}
Mofified aspect targetting int
/Integer
field accessors only:
package de.scrum_master.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.stereotype.Component;
import de.scrum_master.app.DynamicValue;
@Aspect
@Configurable
@Component
public class DynamicValueAspect {
@Pointcut("get(* de.scrum_master.app..*) && @annotation(dynamicValue)")
public void isDynamicValue(DynamicValue dynamicValue) {}
@AfterReturning(pointcut = "isDynamicValue(dynamicValue)", returning = "field")
public void getLocalized(DynamicValue dynamicValue, int field, JoinPoint thisJoinPoint) throws Throwable {
System.out.println(thisJoinPoint);
System.out.println(" " + dynamicValue);
}
}
New console log:
Another member
Hello world
get(int de.scrum_master.app.Application.primitiveNumber)
@de.scrum_master.app.DynamicValue(lookupName=primitive)
11
get(Integer de.scrum_master.app.Application.boxedNumber)
@de.scrum_master.app.DynamicValue(lookupName=boxed)
22
BTW, I answered a similar question here.