1 private static List<String> getParamNames(String methodName, Class<?> clazz) { 2 List<String> paramNames = new ArrayList<>(); 3 ClassPool pool = ClassPool.getDefault(); 4 try { 5 CtClass ctClass = pool.getCtClass(clazz.getName()); 6 CtMethod ctMethod = ctClass.getDeclaredMethod(methodName); 7 // 使用javassist的反射方法的參數名 8 javassist.bytecode.MethodInfo methodInfo = ctMethod.getMethodInfo(); 9 CodeAttribute codeAttribute = methodInfo.getCodeAttribute(); 10 LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag); 11 if (attr != null) { 12 int len = ctMethod.getParameterTypes().length; 13 // 非靜態的成員函數的第一個參數是this 14 int pos = Modifier.isStatic(ctMethod.getModifiers()) ? 0 : 1; 15 for (int i = 0; i < len; i++) { 16 paramNames.add(attr.variableName(i + pos)); 17 } 18 19 } 20 return paramNames; 21 } catch (NotFoundException e) { 22 e.printStackTrace(); 23 return null; 24 } 25 }
這是一個使用Javassist獲取方法參數名稱的函數, 正常情況下執行是沒什么問題的, 但如果在編譯的時候加入 -g:none, 那么第10行則獲取不到任何本地變量的信息.
-g參數的意義, 參考這個鏈接 https://blog.csdn.net/shenzhang/article/details/84399565
所有編譯相關參數可以參考 https://blog.csdn.net/centurymagus/article/details/2097036
簡單來說-g參數編譯之后可以把方法的變量名稱等一起保存在class文件中, 這也是為什么Debug的時候可以查看變量的信息.(加入 -g:none編譯出來的文件不能進行Debug,命中不了任何斷點)
下面是測試截圖:
源碼(可以看到after方法里有個變量名稱為object):
使用-g編譯生成的class文件:
使用-g:none編譯生成的class文件:
所以, springMVC等框架的處理方法一般是根據參數的類型來注入方法參數並invoke調用, 當然可能也支持使用變量名稱, 但是加入-g:none可能會失效, 所以可以借助注解 @RequestParam等來指定名稱