范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

获取Java方法参数名的原理与实践

  前言
  你是否曾经好奇过 SpringMVC 是如何获取方法参数名实现请求参数映射的呢?是反射还是字节码技术?最近群友在知乎回答了该问题,苦于没有博客,特此转载分享 Java 中获取方法参数名的原理。
  ps. 该群友单身优质男青年 ,95后,在线找女票ing,有意者mm
  原文出处:https://zhuanlan.zhihu.com/p/610288146
  作者:xinxi javac 命令
  Java里面获取方法的参数名大概有两种方法,对应的javac的两个选项如下
  -g 选项
  生成调试用的东西,它有三个,lines、vars、source,也就是调试的时候用的行号、参数名和源文件。直接使用 -g 的话会把这三个信息都生成。
  编译时使用 -g 选项,然后使用 javap 可以看到会有一个 LocalVariableTable 块,里面有方法的参数的名字,如下图所示
  -parameters 选项
  直接看效果吧,它有个 MethodParameters 块,如下图
  使用代码获取 LocalVariableTable 块
  我们自己去读取 class 文件貌似有点难度,借助一些处理字节码的框架会比较ok使用ASM  import org.springframework.asm.*;
  import static org.springframework.asm.Opcodes.*;
  public class Main {
  public static void main(String[] args) throws Exception {
  ClassPrinter cp = new ClassPrinter();
  ClassReader cr = new ClassReader("com.example.test.Dog");
  cr.accept(cp, 0);
  }
  }
  class ClassPrinter extends ClassVisitor {
  public ClassPrinter() {
  super(ASM9);
  }
  @Override
  public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
  System.out.println("---------------------------------------");
  System.out.println(name + " | " + desc);
  return new MethodVisitor(ASM9) {
  @Override
  public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
  System.out.println(name + " 	 " + descriptor);
  super.visitLocalVariable(name, descriptor, signature, start, end, index);
  }
  };
  }
  }
  这里用的是 Spring ASM,与原生的差不太多,运行效果如下
  使用javassist  import javassist.ClassPool;
  import javassist.CtClass;
  import javassist.CtMethod;
  import javassist.bytecode.CodeAttribute;
  import javassist.bytecode.LocalVariableAttribute;
  import javassist.bytecode.MethodInfo;
  import java.lang.reflect.Modifier;
  public class Main {
  public static void main(String[] args) throws Exception {
  ClassPool pool = ClassPool.getDefault();
  CtClass ctClass = pool.get("com.example.test.Dog");
  CtMethod ctMethod = ctClass.getDeclaredMethod("func");
  MethodInfo methodInfo = ctMethod.getMethodInfo();
  CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
  LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
  if (attr != ) {
  int len = ctMethod.getParameterTypes().length;
  int pos = Modifier.isStatic(ctMethod.getModifiers()) ? 0 : 1;
  for (int i = 0; i < len; i++) {
  System.out.print(attr.variableName(i + pos) + " ");
  }
  System.out.println();
  }
  }
  }
  运行效果如下
  使用代码获取 MethodParameters 块   import java.lang.reflect.Method;
  import java.lang.reflect.Parameter;
  public class Main {
  public static void main(String[] args) throws Exception {
  Class<?> clazz = Dog.class;
  Method method = clazz.getDeclaredMethod("func", String.class, Integer.class);
  Parameter[] parameters = method.getParameters();
  for (final Parameter parameter : parameters) {
  if (parameter.isNamePresent()) {
  System.out.print(parameter.getName() + " ");
  }
  }
  }
  }
  运行效果如下
  构建工具
  写Java的应该很少有手动 javac 的吧?所以看看构建工具是很有必要的。Maven
  Maven编译代码使用的是 maven-compiler-plugin 插件,看看它是怎么玩的
  amaven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html
  可以看到 debug 默认 true,parameters 默认 false。Gradle
  参考
  adocs.gradle.org/current/dsl/org.gradle.api.tasks.compile.CompileOptions.html
  可以看到 debug 默认是 true。
  没找到 parameters.....你可以自己指定这个选项,默认应该是没有开启这个。SpringBoot 项目 Maven
  如果你是下面这样写的话 <parent>
  <groupId>org.springframework.bootgroupId>
  <artifactId>spring-boot-starter-parentartifactId>
  <version>2.7.7version>
  <relativePath/> 
  parent>
  那么可以看到编译插件被动了点手脚,如下
  还记得么,Maven的编译插件 debug 默认 true,parameters 默认 false,而SpringBoot把parameters也打开了。Gradle
  我们直接查看SpringBoot的Gradle插件源码如下
  还记得么, Gradle编译时debug 默认是 true,parameters 默认 false。而SpringBoot插件会检查如果没有 -parameters 的话,就加上去。Spring 框架
  spring-core 模块中有个 ParameterNameDiscoverer 接口,专门用来获取参数的名字。比较重要的实现是如下两个StandardReflectionParameterNameDiscoverer 类
  使用JDK 8的反射设施来反省参数名称(编译时需指定 -parameters 参数)LocalVariableTableParameterNameDiscoverer 类
  使用 ASM 库来分析类文件,使用方法属性中的 LocalVariableTable 信息来发现参数名称(编译时需指定 -g 参数生成调试信息)
  但是实际上使用的类是 DefaultParameterNameDiscoverer,源代码如下
  一看就应该知道是怎么工作的,把能用的手段都用上对吧。
  测试代码如下 import com.google.common.collect.Lists;
  import org.springframework.core.DefaultParameterNameDiscoverer;
  import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
  import org.springframework.core.StandardReflectionParameterNameDiscoverer;
  public class Main {
  public static void main(String[] args) {
  Lists.newArrayList(
  new LocalVariableTableParameterNameDiscoverer(),
  new StandardReflectionParameterNameDiscoverer(),
  new DefaultParameterNameDiscoverer()
  ).forEach(parameterNameDiscoverer -> {
  try {
  String[] parameterNames = parameterNameDiscoverer
  .getParameterNames(Dog.class.getDeclaredMethod("func", String.class, Integer.class));
  for (String parameterName : parameterNames) {
  System.out.print(parameterName + " ");
  }
  System.out.println();
  } catch (NoSuchMethodException e) {
  throw new RuntimeException(e);
  }
  });
  }
  }
  运行效果如下
  既没有-g也没有-parameters还能抢救一下吗?
  能的。用注解,不过这已经不算是获取方法的参数名了,但也能用不是…

全球折叠屏之王,三星GalaxyZFold4引领行业走向未来文柳华芳美的事物,是永恒的喜悦约翰济慈,19世纪英国浪漫主义诗人。8月22日,杭州,三星GalaxyZFold4ZFlip4GalaxyWatch5Watch5ProGalaxyB洋河2022年中报分析改革红利的释放与富余资金的隐患8月26日,洋河股份发布2022年中报。2022年上半年,公司实现营业收入189。08亿(vs去年同期155。43亿),同比增长21。65实现归母净利为69亿(vs去年同期56。6微软不造车却要闯入一条新赛道头图来源网络微软并没有造车计划,微软在汽车行业的原则是不直接参与竞争,而是专注于服务汽车行业客户。微软中国副总裁微软中国区企业商用事业部总经理袁以拓在2022世界新能源汽车大会期间房价连续两个月下跌,房贷利率跌至4,为何还是无人问津?2022年已经过去了半个月的时间了,在这八个月的时间里面发生了很多事情,其中最值得吐槽的事情就是油价和房地产,对于油价的话,今年上涨的幅度真的是有点奇葩了,今年上半年油价几乎呈直线中通快递完成10亿美元2027年到期可转换优先票据发行2022年9月1日,中通快递(ZTO。US02057。HK)宣布,公司完成10亿美元的2027年到期可转换优先票据发行,其中包含1。3亿美元超额配售,并于8月29日完成交割。据中通央行正式注销两张支付牌照近日,支付圈获悉,福建省掌财通支付服务有限公司安徽圣德天开信息科技有限公司的支付牌照被注销,方式为不予续展,年内被央行注销的支付牌照已达到23张。据了解,此次注销的二家支付机构持有日元贬值新低24年首见,财务相称或将出手干预中文导报讯日元在9月1日再次下挫,颓势明显。日元兑美元汇率一度跌破140水平重要心里关口,低见140。26,创下1998年9月以来新低。自2022年初以来,日元累计跌幅达25。日本人民财评无货源开店躺赚?小心赔了夫人又折兵来源人民网观点频道原创稿零基础无货源,也能开网店无货源开店,月入过万不是梦近来,大量广告在社交及短视频平台兴起,宣称无货源电商是低门槛创业的首选,轻松便可实现宅家赚钱,并顺势推销收阿迪达斯自作孽作者南风窗高级记者杨露市场上,唱衰阿迪达斯的情绪,已经持续了好几年。如今,这个所谓的国际一线运动品牌已沦落为不打折就不买的存在,而其CEO罗斯德在近期的离职新闻,又将为阿迪达斯本已北交所一百单八将上半年营收近445亿同比增速超30券商加速布局寻求业绩突破新高地北交所的设立,揭开我国多层次资本市场的全新篇章。在经历近一年的建设后,北交所已然初具规模,当前总市值接近2000亿元,中小上市企业占比超过七成。9月1日,N昆工(831152。BJ油价即将进行新一轮调整各位车主注意!油价五连跌之后国内油价将于9月6日进行新一轮的油价调整预计油价将要上调国内油价第17轮周期统计已超过半数,预测原油涨幅为6。98,上涨幅度为280元吨,折算后已超过0
机关事业单位退休中人独生子女一次性奖励何时发放?机关事业单位退休中人因并轨需要,2014年前退休养老金中,根据政策而增发的工资5计发在养老金待遇里的部分,在并轨后的重核发中,不再计入养老金待遇。2015年,根据人社部统一安排,全宝宝11个月了学步鞋怎么选好?您好,我是好孕育儿说,很高兴可以回答您的问题。一般11个月的宝宝已经开始学走路了,爸爸妈妈在惊喜兴奋的同时也在担心宝宝学走路时摔跤,此时就需要一双合适的学步鞋。那要怎么给宝宝挑选学多少岁算高龄孕妇,35岁以上算吗?男孩太调皮了,这一胎一定要生个女孩以后小孩终于可以有个伴儿啦,二胎政策的出台,应该是很多妈妈的福音,因为又可以生多一个小宝宝啦然而很多妈妈在高龄孕妇的生育风险面前也望而却步,对于高中国足球大概还要多久才能出成绩?早就出了成绩,只是别人是大班的成绩,而且优秀,你是小班的成绩,而且总是不级格!唯一一次02年级格的成绩还是日韩腾出了空位保送的结果!谁都能看出来!如果教育体制不改变,所有的家长绝对中超历史上最难破纪录的是哪一项?能否选出五项中超的最难破纪录?一,广州恒大升班马夺冠,之后中超七联冠,期间还两夺亚冠。2011赛季,广州恒大以升班马身份升入中国顶级联赛,夺取当年中超冠军,2011年至2017年,广州恒大中超七连冠,在2013佩戴助听器适应期是需要多久?助听器的适应期是因人而异的,一般需要13个月的适应期,这期间声音要从小到大,环境从安静到嘈杂,时间从短到长,需要和验配师积极反馈和沟通,及时调整和评估,尽快度过适应期。看自身情况,华为mate40Pro现阶段值得购买吗?感谢您的阅读!华为mate40Pro现阶段值得买吗?这款手机是华为表现在突出的一款手机,也是华为目前这个系列最强的手机。对于我们来说这款手机它的表现确实有优势,不管是麒麟处理器还可华为mete10por和p20哪个好?我是科技数码随时答,很高兴能回答这个问题华为P20和华为mate10pro那个好?这里首先要说一下,没有那个手机好不好,只有适合不适合自己。华为P系列走的是时尚年轻的产品风格,对相为什么真有人得月子病,却有人说坐月子是陋习?我觉得说坐月子是陋习的人要么是身体素质特别好暂时没有出现月子病的人,要么就是还没有生育且不愿意坐月子的人。说实话,在生孩子之前,我作为一个女的,想到坐月子时要在床上躺一个月,吃各种微信零钱通靠谱吗?有保障吗?微信零钱通,是微信支付推出的一款支付零钱理财的综合服务,功能与用法和余额宝完全类似,是非常靠谱的。说它靠谱,主要有以下几个原因一是微信支付是大型移动支付公司,背靠腾讯,实力强大二是通胀之下老百姓如何应对?节衣缩食,省吃减用,别无选择。衣服有穿的不再买新的,生活一日三餐吃饱就行。收入不增长,物价再涨高,老百姓能有啥法,只能节省支出,保持生活相对稳定。通胀之下,老百姓怎么应对都是没有用