Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring AOP: get access to argument names

I'm using Spring 3.x, Java 6.

I have an @Around aspect with the following joinpoint:

@Around("execution(public * my.service.*.*Connector.*(..))")

So, I'm basically interested in intercepting all calls to public methods of classes with the class name ending with "Connector". So far so good.

Now, in my aspect I would like to access the actual argument names of the methods:

public doStuff(String myarg, Long anotherArg)

myarg and anotherArg

I understand that using:

CodeSignature signature = (CodeSignature)jointPoint.getSignature();
return signature.getParameterNames();

will actually work but only if I compile the code with the "-g" flag (full debug) and I would rather not do it.

Is there any other way to get access to that kind of runtime information.

Thanks L

like image 255
Luciano Fiandesio Avatar asked Feb 17 '11 15:02

Luciano Fiandesio


2 Answers

Unfortunately you can't do this :-(. It is a well known limitation of JVM/bytecode - argument names can't be obtained using reflection, as they are not always stored in bytecode (in the contrary to method/class names).

As a workaround several frameworks/specification introduce custom annotations over arguments like WebParam (name property) or PathParam.

For the time being all you can get without annotations is an array of values.

like image 52
Tomasz Nurkiewicz Avatar answered Oct 03 '22 13:10

Tomasz Nurkiewicz


Check the implementations of org.springframework.core.ParameterNameDiscoverer.

Annotations like @RequestParam used by spring inspect the parameter name if no value is set. So @RequestParam String foo will in fact fetch the request parameter named "foo". It uses the ParameterNameDiscoverer mechanism. I'm just not sure which of the implementations are used, by try each of them.

The LocalVariableTableParameterNameDiscoverer reads the .class and uses asm to inspect the names.

So, it is possible. But make sure to cache this information (for example - store a parameter name in a map, with key = class+method+parameter index).

But, as it is noted in the docs, you need the debug information. From the docs of @PathVariable:

The matching of method parameter names to URI Template variable names can only be done if your code is compiled with debugging enabled. If you do not have debugging enabled, you must specify the name of the URI Template variable name in the @PathVariable annotation in order to bind the resolved value of the variable name to a method parameter

So, if you really don't want to include that information, Tomasz Nurkiewicz's answer explains the workaround.

like image 27
Bozho Avatar answered Oct 03 '22 13:10

Bozho