1、MethodParameter的API
MethodParameter主要用于表示方法或构造器的参数,加上参数索引和已声明泛型类型的嵌套类型索引。
其中Executable的UML图如下:
(1)、MethodParameter的字段
// 代表该参数所在的方法,对应的反射类Method
private final Executable executable;
// 标记参数索引
private final int parameterIndex;
// 反射对应的方法参数类型
@Nullable
private volatile Parameter parameter;
// 嵌套级别
private int nestingLevel;
// 类型索引级别
/** Map from Integer level to Integer type index. */
@Nullable
Map<Integer, Integer> typeIndexesPerLevel;
// 缺省情况下表示该参数所在方法的所在类
/** The containing class. Could also be supplied by overriding {@link #getContainingClass()} */
@Nullable
private volatile Class<?> containingClass;
// 代表参数类型
@Nullable
private volatile Class<?> parameterType;
// 代表该方法参数中的泛型类型
@Nullable
private volatile Type genericParameterType;
// 表示该方法参数被标记的注解类型数组
@Nullable
private volatile Annotation[] parameterAnnotations;
// 方法参数名解析器
@Nullable
private volatile ParameterNameDiscoverer parameterNameDiscoverer;
// 方法参数名称
@Nullable
private volatile String parameterName;
// 嵌套方法参数
@Nullable
private volatile MethodParameter nestedMethodParameter;
(2)、MethodParameter中的构造器
/**
* Create a new {@code MethodParameter} for the given method, with nesting level 1.
* @param method the Method to specify a parameter for
* @param parameterIndex the index of the parameter: -1 for the method
* return type; 0 for the first method parameter; 1 for the second method
* parameter, etc.
*/
public MethodParameter(Method method, int parameterIndex) {
this(method, parameterIndex, 1);
}
/**
* Create a new {@code MethodParameter} for the given method.
* @param method the Method to specify a parameter for
* @param parameterIndex the index of the parameter: -1 for the method
* return type; 0 for the first method parameter; 1 for the second method
* parameter, etc.
* @param nestingLevel the nesting level of the target type
* (typically 1; e.g. in case of a List of Lists, 1 would indicate the
* nested List, whereas 2 would indicate the element of the nested List)
*/
public MethodParameter(Method method, int parameterIndex, int nestingLevel) {
Assert.notNull(method, "Method must not be null");
this.executable = method;
this.parameterIndex = validateIndex(method, parameterIndex);
this.nestingLevel = nestingLevel;
}
/**
* Create a new MethodParameter for the given constructor, with nesting level 1.
* @param constructor the Constructor to specify a parameter for
* @param parameterIndex the index of the parameter
*/
public MethodParameter(Constructor<?> constructor, int parameterIndex) {
this(constructor, parameterIndex, 1);
}
/**
* Create a new MethodParameter for the given constructor.
* @param constructor the Constructor to specify a parameter for
* @param parameterIndex the index of the parameter
* @param nestingLevel the nesting level of the target type
* (typically 1; e.g. in case of a List of Lists, 1 would indicate the
* nested List, whereas 2 would indicate the element of the nested List)
*/
public MethodParameter(Constructor<?> constructor, int parameterIndex, int nestingLevel) {
Assert.notNull(constructor, "Constructor must not be null");
this.executable = constructor;
this.parameterIndex = validateIndex(constructor, parameterIndex);
this.nestingLevel = nestingLevel;
}
/**
* Internal constructor used to create a {@link MethodParameter} with a
* containing class already set.
* @param executable the Executable to specify a parameter for
* @param parameterIndex the index of the parameter
* @param containingClass the containing class
* @since 5.2
*/
MethodParameter(Executable executable, int parameterIndex, @Nullable Class<?> containingClass) {
Assert.notNull(executable, "Executable must not be null");
this.executable = executable;
this.parameterIndex = validateIndex(executable, parameterIndex);
this.nestingLevel = 1;
this.containingClass = containingClass;
}
/**
* Copy constructor, resulting in an independent MethodParameter object
* based on the same metadata and cache state that the original object was in.
* @param original the original MethodParameter object to copy from
*/
public MethodParameter(MethodParameter original) {
Assert.notNull(original, "Original must not be null");
this.executable = original.executable;
this.parameterIndex = original.parameterIndex;
this.parameter = original.parameter;
this.nestingLevel = original.nestingLevel;
this.typeIndexesPerLevel = original.typeIndexesPerLevel;
this.containingClass = original.containingClass;
this.parameterType = original.parameterType;
this.genericParameterType = original.genericParameterType;
this.parameterAnnotations = original.parameterAnnotations;
this.parameterNameDiscoverer = original.parameterNameDiscoverer;
this.parameterName = original.parameterName;
}
构造器方法中主要有两种方式构造一种是通过提供Method,另一种是提供Constructor的方式。
主要说明下这个类的一些方法:
(3)、MethodParameter中的方法
getMethod:
/**
* Return the wrapped Method, if any.
* <p>Note: Either Method or Constructor is available.
* @return the Method, or {@code null} if none
*/
@Nullable
public Method getMethod() {
// 判断executable对象是否为Method类型。
return (this.executable instanceof Method ? (Method) this.executable : null);
}
getConstructor:
/**
* Return the wrapped Constructor, if any.
* <p>Note: Either Method or Constructor is available.
* @return the Constructor, or {@code null} if none
*/
@Nullable
public Constructor<?> getConstructor() {
// 判断executable对象的类型是否为构造器类型。
return (this.executable instanceof Constructor ? (Constructor<?>) this.executable : null);
}
getDeclaringClass:
/**
* Return the class that declares the underlying Method or Constructor.
*/
public Class<?> getDeclaringClass() {
// 获取executable所在的类的类型。
return this.executable.getDeclaringClass();
}
getAnnotatedElement:
/**
* Return the wrapped annotated element.
* <p>Note: This method exposes the annotations declared on the method/constructor
* itself (i.e. at the method/constructor level, not at the parameter level).
* @return the Method or Constructor as AnnotatedElement
*/
public AnnotatedElement getAnnotatedElement() {
return this.executable;
}
这个接口(AnnotatedElement)的对象代表了在当前JVM中的一个“被注解元素”(可以是Class,Method,Field,Constructor,Package等)。
在Java语言中,所有实现了这个接口的“元素”都是可以“被注解的元素”。使用这个接口中声明的方法可以读取(通过Java的反射机制)“被注解元素”的注解。这个接口中的所有方法返回的注解都是不可变的、并且都是可序列化的。这个接口中所有方法返回的数组可以被调用者修改,而不会影响其返回给其他调用者的数组。
子接口:
AnnotatedArrayType (被注解的数组类型)
AnnotatedParameterizedType (被注解的参数化类型)
AnnotatedType (被注解的类型)
AnnotatedTypeVariable (被注解的类型变量)
AnnotatedWildcardType (被注解的通配类型)
GenericDeclaration (通用声明,用于表示声明型元素,如:类、方法、构造器等)
TypeVariable
实现类:
AccessibleObject(可访问对象,如:方法、构造器、属性等)
Class(类,就是你用Java语言编程时每天都要写的那个东西)
Constructor(构造器,类的构造方法的类型)
Executable(可执行的,如构造器和方法)
Field(属性,类中属性的类型)
Method(方法,类中方法的类型)
Package(包,你每天都在声明的包的类型)
Parameter(参数,主要指方法或函数的参数,其实是这些参数的类型)
getAnnotationsByType(Class)和getDeclaredAnnotationsByType(Class)方法在一个元素上支持多个相同类型的注释。
getParameter:
/**
* Return the {@link Parameter} descriptor for method/constructor parameter.
* @since 5.0
*/
public Parameter getParameter() {
if (this.parameterIndex < 0) {
throw new IllegalStateException("Cannot retrieve Parameter descriptor for method return type");
}
// 获取方法中对应索引的参数。
Parameter parameter = this.parameter;
if (parameter == null) {
parameter = getExecutable().getParameters()[this.parameterIndex];
this.parameter = parameter;
}
return parameter;
}
nested方法:
实质上是对MethodParameter的clone,至于为什么需要nested,尚且不知。代码如下:
/**
* Return a variant of this {@code MethodParameter} which points to the
* same parameter but one nesting level deeper.
* @since 4.3
*/
public MethodParameter nested() {
return nested(null);
}
/**
* Return a variant of this {@code MethodParameter} which points to the
* same parameter but one nesting level deeper.
* @param typeIndex the type index for the new nesting level
* @since 5.2
*/
public MethodParameter nested(@Nullable Integer typeIndex) {
MethodParameter nestedParam = this.nestedMethodParameter;
if (nestedParam != null && typeIndex == null) {
return nestedParam;
}
nestedParam = nested(this.nestingLevel + 1, typeIndex);
if (typeIndex == null) {
this.nestedMethodParameter = nestedParam;
}
return nestedParam;
}
private MethodParameter nested(int nestingLevel, @Nullable Integer typeIndex) {
// clone下。
MethodParameter copy = clone();
// 将嵌套级别更新下。
copy.nestingLevel = nestingLevel;
if (this.typeIndexesPerLevel != null) {
copy.typeIndexesPerLevel = new HashMap<>(this.typeIndexesPerLevel);
}
if (typeIndex != null) {
copy.getTypeIndexesPerLevel().put(copy.nestingLevel, typeIndex);
}
// parameterType和genericParameterType都需要重新计算。
copy.parameterType = null;
copy.genericParameterType = null;
return copy;
}
withContainingClass方法:
/**
* Return a variant of this {@code MethodParameter} which refers to the
* given containing class.
* @param containingClass a specific containing class (potentially a
* subclass of the declaring class, e.g. substituting a type variable)
* @since 5.2
* @see #getParameterType()
*/
public MethodParameter withContainingClass(@Nullable Class<?> containingClass) {
MethodParameter result = clone();
// 设置方法参数所在的类的类型。
result.containingClass = containingClass;
result.parameterType = null;
return result;
}
getParameterType方法:获取方法参数的类型。
/**
* Return the type of the method/constructor parameter.
* @return the parameter type (never {@code null})
*/
public Class<?> getParameterType() {
Class<?> paramType = this.parameterType;
if (paramType != null) {
return paramType;
}
if (getContainingClass() != getDeclaringClass()) {
paramType = ResolvableType.forMethodParameter(this, null, 1).resolve();
}
// 如果index的值为-1那么就返回返回值类型,否则就使用反射来获取方法index的参数类型
if (paramType == null) {
paramType = computeParameterType();
}
this.parameterType = paramType;
return paramType;
}
getGenericParameterType方法:
/**
* Return the generic type of the method/constructor parameter.
* @return the parameter type (never {@code null})
* @since 3.0
*/
public Type getGenericParameterType() {
Type paramType = this.genericParameterType;
if (paramType == null) {
// 如果是返回值类型
if (this.parameterIndex < 0) {
Method method = getMethod();
paramType = (method != null ?
(KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(getContainingClass()) ?
KotlinDelegate.getGenericReturnType(method) : method.getGenericReturnType()) : void.class);
}
else {
// 获取方法中的所有泛型类型。
Type[] genericParameterTypes = this.executable.getGenericParameterTypes();
int index = this.parameterIndex;
if (this.executable instanceof Constructor &&
ClassUtils.isInnerClass(this.executable.getDeclaringClass()) &&
genericParameterTypes.length == this.executable.getParameterCount() - 1) {
// Bug in javac: type array excludes enclosing instance parameter
// for inner classes with at least one generic constructor parameter,
// so access it with the actual parameter index lowered by 1
index = this.parameterIndex - 1;
}
paramType = (index >= 0 && index < genericParameterTypes.length ?
genericParameterTypes[index] : computeParameterType());
}
this.genericParameterType = paramType;
}
return paramType;
}
getParameterAnnotations方法:
/**
* Return the annotations associated with the specific method/constructor parameter.
*/
public Annotation[] getParameterAnnotations() {
Annotation[] paramAnns = this.parameterAnnotations;
if (paramAnns == null) {
// 通过反射获取参数的所有注解类型。
Annotation[][] annotationArray = this.executable.getParameterAnnotations();
int index = this.parameterIndex;
if (this.executable instanceof Constructor &&
ClassUtils.isInnerClass(this.executable.getDeclaringClass()) &&
annotationArray.length == this.executable.getParameterCount() - 1) {
// Bug in javac in JDK <9: annotation array excludes enclosing instance parameter
// for inner classes, so access it with the actual parameter index lowered by 1
index = this.parameterIndex - 1;
}
paramAnns = (index >= 0 && index < annotationArray.length ?
adaptAnnotationArray(annotationArray[index]) : EMPTY_ANNOTATION_ARRAY);
this.parameterAnnotations = paramAnns;
}
return paramAnns;
}