Spring AOP: get access to argument names

眉间皱痕 提交于 2019-11-29 02:24:25

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.

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.

In Java 8 there is a new compiler flag that allows additional metadata to be stored with byte code and these parameter names can be extracted using the Parameter object in reflection. See JDK 8 spec. In newer versions of hibernate org.springframework.core.ParameterNameDiscoverer uses this feature. To use it compile using javac with this flag:

-parameters                Generate metadata for reflection on method parameters

Access parameters using reflection's Parameter class.

I am not sure if its a best way, but I added a Annotation on my method:

My Annotation:

@Retention (RetentionPolicy.RUNTIME)
@Target (ElementType.METHOD)
public @interface ReadApi
{
    String[] paramNames() default "";
}

@ReadApi (paramNames={"name","id","phone"})
public Address findCustomerInfo(String name, String id, String phone)
{ ..... }

And in the Aspect:

@Around("aspect param && @annotation(readApi)")
public Object logParams(ProceedingJoinPoint pjp,
        ReadApi readApi) 
{
    //use pjp.getArgs() and readApi.paramNames();
}

This is probably a hack but i did not want to compile with more options to get information. Anyways, its working well for me. Only downside is that i need to keep the names in annotation and method in sync.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!