Spring AOP:访问参数名称

发布于 2024-10-18 01:23:15 字数 629 浏览 1 评论 0原文

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

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

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

因此,我基本上有兴趣拦截对类名以“Connector”结尾的类的公共方法的所有调用。到目前为止,一切都很好。

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

public doStuff(String myarg, Long anotherArg)

myarganotherArg

我明白 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

懒猫 2024-10-25 01:23:15

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

作为解决方法 多个框架/规范在参数上引入了自定义注释,例如 < code>WebParamname 属性)或 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) or PathParam.

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

风透绣罗衣 2024-10-25 01:23:15

检查 org.springframework.core.ParameterNameDiscoverer 的实现。

如果没有设置 value,Spring 使用的诸如 @RequestParam 之类的注释会检查参数名称。因此 @RequestParam String foo 实际上会获取名为“foo”的请求参数。它使用ParameterNameDiscoverer机制。我只是不确定使用了哪些实现,请尝试每个实现。

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

所以,这是可能的。但请确保缓存此信息(例如 - 将参数名称存储在映射中,其中键 = 类+方法+参数索引)。

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

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

因此,如果您确实不想包含根据该信息,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.

琉璃梦幻 2024-10-25 01:23:15

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

-parameters                Generate metadata for reflection on method parameters

使用反射的 参数 类。

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.

水晶透心 2024-10-25 01:23:15

我不确定这是否是最好的方法,但我在我的方法上添加了注释:

我的注释:

@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();
}

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文