xierui
xierui

Reputation: 1055

how can spring get args name from the method

In spring, it express the arg-names like this :

@Before(
value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && @annotation(auditable)",
argNames="bean,auditable")
public void audit(JoinPoint jp, Object bean, Auditable auditable) {
    AuditCode code = auditable.value();
// ... use code, bean, and jp
}

In the doc , it says you may leave out the name of the parameter from the value of the "argNames" attribute. How can spring get argNames("bean,auditable") from anyPublicMethod?

Did java provide some api to get the parameter names?

I think it use the aspectJ to parse the expression, did aspectJ provide the feature?

Upvotes: 0

Views: 1461

Answers (3)

Serge Ballesta
Serge Ballesta

Reputation: 149145

Just a complement to the other answers. Spring documentation is explicit : Spring does its best to retrieve correct parameters :

  • if using Java 8 it uses Java 8 reflection
  • if classes are compiled in debug mode, parameter name is present and spring uses it, same if ajc (aspectJ compiler) has been used)
  • it can eventually uses @Param annotations
  • it uses the type if not ambiguous

Upvotes: 0

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 136102

In Java 8 we can use reflection to get parameter name, see http://docs.oracle.com/javase/tutorial/reflect/member/methodparameterreflection.html. Though argument names will be present if the classes have been compiled with -g:vars.

In earlier versions we need to use some tool, like Javassist:

public static void main(String[] args) throws Exception {
    ClassPool pool = ClassPool.getDefault();
    CtClass c = pool.get("test.Test");
    CtMethod m = c.getDeclaredMethod("main");
    MethodInfo methodInfo = m.getMethodInfo();
    LocalVariableAttribute t = (LocalVariableAttribute) methodInfo.getCodeAttribute().getAttribute(javassist.bytecode.LocalVariableAttribute.tag);
    int i = t.nameIndex(0); 
    String v = methodInfo.getConstPool().getUtf8Info(i);
    System.out.println(v); 
}

prints

args

Upvotes: 2

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 280138

Your annotation

@Before(
value="com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && @annotation(auditable)",
argNames="bean,auditable")

, assuming anyPublicMethod() matches any public method, will match any public method annotated with whatever type a parameter named auditable is and invoked on an object of bound to the parameter named bean.

In your method, a parameter named auditable is of type Auditable, so this @Before advice would match something like

public class SomeComponent {
    @Auditable
    public void someMethod() {}
}

I will bind the SomeComponent type bean to the bean parameter and the instance for the @Auditable annotation to the auditable parameter when invoking the advice.

Java does not have an API for getting parameter names. Parameter names are also not always present in the byte code. When they are, Spring uses the ASM library to parse the bytecode and retrieve them.

Upvotes: 0

Related Questions