我们都知道,Java源文件在编译成class文件后,所有的方法的参数名称信息都会丢失,因为方法的参数对于程序的运行毫无意义,之所以存在是为了提高程序的可读性,所有在编译之后就去掉了参数信息。但是很多程序在运行时又需要方法的参数信息,例如SpringMVC的在处理请求入参的时候。
@RequestMapping("hello")
public void getEnums(String name, String address)
前端入参name和address,是如何与方法中的name和address绑定上的?
在Java8中,提供了编译时参数-parameters
,之后就可以通过反射的机制,获取方法参数信息。使用-parameters
编译的字节码中会带有MethodParameters
属性,使用StandardReflectionParameterNameDiscoverer#getParameterNames
来获取。
如果需要在Java8中开启参数获取,可如下配置maven插件
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<compilerArgument>-parameters</compilerArgument>
</configuration>
</plugin>
Java8之前,可以通过开启调试模式,即编译时添加编译参数-g
。使用-g
编译的字节码中会带有LocalVariableTable
属性,使用Spring中的LocalVariableTableParameterNameDiscoverer#getParameterNames
通过ASM
框架来获取。
但是在我们正常使用Maven开发SpringMVC的过程中,并没有添加这些编译参数,SpringMVC又是如何实现参数绑定的呢?
原因就是Maven的compiler编译插件默认帮我们做了这件事。
Maven compiler插件有个debug属性,默认是true。如果改成false,则SpringMVC的参数注入会失效。
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<debug>false</debug>
</configuration>
</plugin>
所以ASM
框架获取参数名称也是有前提条件的,必须添加-g
编译参数,否则该框架也是不可能能从class文件中猜出原始的参数名称。