闽公网安备 35020302035485号
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也可以解析出来相应的参数名称。