Spring AOP:访问参数名称

我正在使用Spring 3.x,Java 6。

我有一个带有以下连接点的@Around方面:

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

所以,我基本上有兴趣拦截所有对类的公共方法的调用,类名以“Connector”结尾。 到现在为止还挺好。

现在,在我的方面,我想访问方法的实际参数名称:

 public doStuff(String myarg, Long anotherArg) 

myarg另一个Arg

我明白使用:

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

将实际工作,但只有当我使用“ -g ”标志(完全调试)编译代码时,我宁愿不这样做。

有没有其他方法可以访问这种运行时信息。

谢谢你

不幸的是你不能这样做:-(。这是一个众所周知的JVM /字节码限制 – 使用reflection无法获得参数名称,因为它们并不总是存储在字节码中(与方法/类名相反) 。

作为一种解决方法,几个框架/规范在WebParamname属性)或PathParam等参数上引入自定义注释。

目前,没有注释的所有内容都是一系列值。

检查org.springframework.core.ParameterNameDiscoverer

如果没有设置value ,spring使用的@RequestParam注释会检查参数名称。 所以@RequestParam String foo实际上将获取名为“foo”的请求参数。 它使用ParameterNameDiscoverer机制。 我只是不确定使用哪个实现,通过尝试它们中的每一个。

LocalVariableTableParameterNameDiscoverer读取.class并使用asm来检查名称。

所以,这是可能的。 但请确保缓存此信息(例如 – 使用key = class + method + parameter index将参数名称存储在地图中)。

但是,正如文档中所述,您需要调试信息。 来自@PathVariable的文档:

只有在启用调试的情况下编译代码时,才能将方法参数名称与URI模板变量名称匹配。 如果未启用调试,则必须在@PathVariable注释中指定URI模板变量名称的名称,以便将已解析的变量名称值绑定到方法参数

所以,如果你真的不想包含这些信息,Tomasz Nurkiewicz的答案解释了解决方法。

在Java 8中,有一个新的编译器标志,允许使用字节代码存储其他元数据,并且可以使用reflection中的Parameter对象提取这些参数名称。 请参阅JDK 8规范 。 在较新版本的hibernate中,org.springframework.core.ParameterNameDiscoverer使用此function。 要使用它,请使用带有此标志的javac进行编译:

 -parameters Generate metadata for reflection on method parameters 

使用reflection的Parameter类访问参数。

我不确定它是否是最好的方法,但我在我的方法上添加了一个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) { ..... } 

在方面:

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

这可能是一个黑客,但我不想编译更多选项来获取信息。 无论如何,它对我来说效果很好。 唯一的缺点是我需要保持注释和方法中的名称同步。