2.可以提高IDE的功能
//自定义@param注解 @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Param { String value(); } //声明参数名 public void foo(@Param("name") String name, @Param("count") int count){ System.out.println("name:=" + name + ",count=" + count); } //获取 Method foo = ParameterDemo.class.getMethod("foo", String.class, int.class); Annotation[][] parameterAnnotations = foo.getParameterAnnotations(); for (Annotation[] parameterAnnotation : parameterAnnotations) { for (Annotation annotation : parameterAnnotation) { if(annotation instanceof Param){ System.out.println(((Param) annotation).value()); } } } //获取结果 name count通过解析class文件
//使用Spring的LocalVariableTableParameterNameDiscoverer获取 public void foo(String name, int count){ System.out.println("name:=" + name + ",count=" + count); } Method foo = ParameterDemo.class.getMethod("foo", String.class, int.class); String[] parameterNames = new LocalVariableTableParameterNameDiscoverer().getParameterNames(foo); System.out.println(Arrays.toString(parameterNames)); //获取结果 [name, count]
public void foo(String name, int count){ System.out.println("name:=" + name + ",count=" + count); } //堆代码 duidaima.com //通过反射获取 Method foo = ParameterDemo.class.getMethod("foo", String.class, int.class); Parameter[] parameters = foo.getParameters(); for (Parameter parameter : parameters) { System.out.println(parameter.getName()); } //获取结果 name count【注意】
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>8</source> <target>8</target> <compilerArgs> <compilerArg>-parameters</compilerArg> </compilerArgs> </configuration> </plugin>【原理】
//截取片段 public void foo(java.lang.String, int); descriptor: (Ljava/lang/String;I)V flags: ACC_PUBLIC Code: stack=3, locals=3, args_size=3 0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 3: new #3 // class java/lang/StringBuilder 6: dup 7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V 10: ldc #5 // String name:= 12: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 15: aload_1 16: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 19: ldc #7 // String ,count= 21: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 24: iload_2 25: invokevirtual #8 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 28: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 31: invokevirtual #10 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 34: return LineNumberTable: line 14: 0 line 15: 34 LocalVariableTable: Start Length Slot Name Signature 0 35 0 this Lcom/sevenlin/demo/reflect/ParameterDemo; 0 35 1 name Ljava/lang/String; 0 35 2 count I MethodParameters: Name Flags name count
@Component @Endpoint(id = "my", enableByDefault = true) //设置 id,并选择是否默认开启 public class MyEndPoint { @ReadOperation public List<String> getPaths() { List<String> list = new ArrayList<>(); list.add("java"); list.add("c++"); list.add("python"); return list; } @ReadOperation public String get(@Selector String arg0) { return arg0; } @WriteOperation public String post() { return "post"; } @DeleteOperation public Integer delete() { return 1; } }上面的 Endpoint 有一个 @Selector 参数的方法,并且参数名是 arg0,这个参数名是有学问滴. 如果改成一个有意义的名字是可以的吗?原来给的参数名是 path,原来设想可以访问 /actuator/my/[任意字符] 的路径,但是会报 400 参数不匹配错误。但是,/actuator/my/[任意字符]?path=[任意字符] 是正常访问的。
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <compilerArgs> <arg>-parameters</arg> </compilerArgs> </configuration> </plugin>或者:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <parameters>true</parameters> </configuration> </plugin> --> </plugins></pre>原因就是spring解析参数的类为
public class DefaultParameterNameDiscoverer extends PrioritizedParameterNameDiscoverer { public DefaultParameterNameDiscoverer() { if (KotlinDetector.isKotlinReflectPresent() && !NativeDetector.inNativeImage()) { this.addDiscoverer(new KotlinReflectionParameterNameDiscoverer()); } this.addDiscoverer(new StandardReflectionParameterNameDiscoverer()); this.addDiscoverer(new LocalVariableTableParameterNameDiscoverer()); } }它的解析顺序为StandardReflectionParameterNameDiscoverer->LocalVariableTableParameterNameDiscoverer
public String[] getParameterNames(Method method) { Iterator var2 = this.parameterNameDiscoverers.iterator(); String[] result; do { if (!var2.hasNext()) { return null; } ParameterNameDiscoverer pnd = (ParameterNameDiscoverer)var2.next(); result = pnd.getParameterNames(method); } while(result == null); return result; }从代码上看,StandardReflectionParameterNameDiscoverer 比LocalVariableTableParameterNameDiscoverer先解析。在由于在JDK 缺省编译情况下,class 不包含parameter 名字信息,因此StandardReflectionParameterNameDiscoverer只有arg0 可以辨认,但是确实能够解析出来,因此LocalVariableTableParameterNameDiscoverer就用不到了。 如果加入编译参数,StandardReflectionParameterNameDiscoverer也可以解析出来相应的参数名称。