标签:
一般来说,通过反射是很难获得参数名的,只能取到参数类型,因为在编译时,参数名有可能是会改变的,需要在编译时加入参数才不会改变。
使用注解是可以实现取类型名(或者叫注解名)的,但是要写注解,并不方便。
观察Spring mvc框架中的数据绑定,发现是可以直接把http请求中对应参数绑定到对应的参数名上的,他是怎么实现的呢?
先参考一下自动绑定的原理:Spring源码研究:数据绑定
在getMethodArgumentValues方法中,MethodParameter[] parameters = getMethodParameters();这一句取到方法的所有参数,MethodParameter类型中有方法名的属性,这个是什么类呢?
是spring核心中的一个类,org.springframework.core.MethodParameter,并不是通过反射实现的。
方法getMethodParameters()是在HandlerMethod的类中
public MethodParameter[] getMethodParameters() { return this.parameters; }
this.parameters则是在构造方法中初始化的:
public HandlerMethod(Object bean, Method method) { Assert.notNull(bean, "Bean is required"); Assert.notNull(method, "Method is required"); this.bean = bean; this.beanFactory = null; this.method = method; this.bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); this.parameters = initMethodParameters(); }
initMethodParameters()生成了参数列表。
private MethodParameter[] initMethodParameters() { int count = this.bridgedMethod.getParameterTypes().length; MethodParameter[] result = new MethodParameter[count]; for (int i = 0; i < count; i++) { result[i] = new HandlerMethodParameter(i); } return result; }
HandlerMethodParameter(i)是HandlerMethod的内部类,继承自MethodParameter
构造方法调用:
public HandlerMethodParameter(int index) { super(HandlerMethod.this.bridgedMethod, index); }
再调用MethodParameter类的构造方法:
public MethodParameter(Method method, int parameterIndex, int nestingLevel) { Assert.notNull(method, "Method must not be null"); this.method = method; this.parameterIndex = parameterIndex; this.nestingLevel = nestingLevel; this.constructor = null; }
MethodParameter类中有private String parameterName;储存的就是参数名,但是构造方法中并没有设置他的值,真正设置值是在:
public String getParameterName() { if (this.parameterNameDiscoverer != null) { String[] parameterNames = (this.method != null ? this.parameterNameDiscoverer.getParameterNames(this.method) : this.parameterNameDiscoverer.getParameterNames(this.constructor)); if (parameterNames != null) { this.parameterName = parameterNames[this.parameterIndex]; } this.parameterNameDiscoverer = null; } return this.parameterName; }
那这个类中又是如何存储了参数名呢?
标签:
原文地址:http://www.cnblogs.com/guangshan/p/4660564.html