Spring AOP:访问参数名称
我正在使用 Spring 3.x、Java 6。
我有一个带有以下连接点的 @Around 方面:
@Around("execution(public * my.service.*.*Connector.*(..))")
因此,我基本上有兴趣拦截对类名以“Connector”结尾的类的公共方法的所有调用。到目前为止,一切都很好。
现在,在我看来,我想访问方法的实际参数名称:
public doStuff(String myarg, Long anotherArg)
myarg 和 anotherArg
我明白 using:
CodeSignature signature = (CodeSignature)jointPoint.getSignature();
return signature.getParameterNames();
实际上会起作用,但前提是我编译代码使用“-g”标志(完全调试),我宁愿不这样做。
有没有其他方法可以访问此类运行时信息。
谢谢 L
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不幸的是你不能这样做:-(。这是 JVM/字节码的一个众所周知的限制 - 参数名称无法使用反射获得,因为它们并不总是存储在字节码中(与方法/类名称相反) ,
作为解决方法 多个框架/规范在参数上引入了自定义注释,例如 < code>WebParam(
name
属性)或PathParam
。目前,您在没有注释的情况下可以获得的只是一个值数组。
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) orPathParam
.For the time being all you can get without annotations is an array of values.
检查 org.springframework.core.ParameterNameDiscoverer 的实现。
如果没有设置
value
,Spring 使用的诸如@RequestParam
之类的注释会检查参数名称。因此 @RequestParam String foo 实际上会获取名为“foo”的请求参数。它使用ParameterNameDiscoverer
机制。我只是不确定使用了哪些实现,请尝试每个实现。LocalVariableTableParameterNameDiscoverer
读取.class
并使用 asm 来检查名称。所以,这是可能的。但请确保缓存此信息(例如 - 将参数名称存储在映射中,其中键 = 类+方法+参数索引)。
但是,正如文档中所述,您需要调试信息。来自
@PathVariable
的文档:因此,如果您确实不想包含根据该信息,Tomasz Nurkiewicz 的回答解释了解决方法。
Check the implementations of
org.springframework.core.ParameterNameDiscoverer
.Annotations like
@RequestParam
used by spring inspect the parameter name if novalue
is set. So@RequestParam String foo
will in fact fetch the request parameter named "foo". It uses theParameterNameDiscoverer
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
:So, if you really don't want to include that information, Tomasz Nurkiewicz's answer explains the workaround.
在 Java 8 中,有一个新的编译器标志,允许使用字节代码存储附加元数据,并且可以使用反射中的 Parameter 对象提取这些参数名称。请参阅 JDK 8 规范。在较新版本的 hibernate org.springframework.core.ParameterNameDiscoverer 中使用此功能。要使用它,请使用带有此标志的
javac
进行编译:使用反射的 参数 类。
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: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:
And in the Aspect:
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.