序
在 mybatis 的 interceptor 获取 MapperMethod.ParamMap 这种参数类型时,常常会多出 param1,param2,collection,list,array 这些参数,这些不是接口本人定义的,而是 ParamNameResolver 主动增加的
ParamNameResolver
org/apache/ibatis/reflection/ParamNameResolver.java
public class ParamNameResolver {
public static final String GENERIC_NAME_PREFIX = "param";
/**
* <p>
* A single non-special parameter is returned without a name.
* Multiple parameters are named using the naming rule.
* In addition to the default names, this method also adds the generic names (param1, param2,
* ...).
* </p>
*
* @param args
* the args
* @return the named params
*/
public Object getNamedParams(Object[] args) {final int paramCount = names.size();
if (args == null || paramCount == 0) {return null;} else if (!hasParamAnnotation && paramCount == 1) {Object value = args[names.firstKey()];
return wrapToMapIfCollection(value, useActualParamName ? names.get(0) : null);
} else {final Map<String, Object> param = new ParamMap<>();
int i = 0;
for (Map.Entry<Integer, String> entry : names.entrySet()) {param.put(entry.getValue(), args[entry.getKey()]);
// add generic param names (param1, param2, ...)
final String genericParamName = GENERIC_NAME_PREFIX + (i + 1);
// ensure not to overwrite parameter named with @Param
if (!names.containsValue(genericParamName)) {param.put(genericParamName, args[entry.getKey()]);
}
i++;
}
return param;
}
}
//......
}
getNamedParams 办法针对单个参数没有加 @Param 的场景会调用 wrapToMapIfCollection,其余的则应用 param1,param2 这种,这里用了 contains,也就是如果自身命名就有蕴含 param1,param2 这种则不会增加
wrapToMapIfCollection
org/apache/ibatis/reflection/ParamNameResolver.java
/**
* Wrap to a {@link ParamMap} if object is {@link Collection} or array.
*
* @param object a parameter object
* @param actualParamName an actual parameter name
* (If specify a name, set an object to {@link ParamMap} with specified name)
* @return a {@link ParamMap}
* @since 3.5.5
*/
public static Object wrapToMapIfCollection(Object object, String actualParamName) {if (object instanceof Collection) {ParamMap<Object> map = new ParamMap<>();
map.put("collection", object);
if (object instanceof List) {map.put("list", object);
}
Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object));
return map;
} else if (object != null && object.getClass().isArray()) {ParamMap<Object> map = new ParamMap<>();
map.put("array", object);
Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object));
return map;
}
return object;
}
wrapToMapIfCollection 对于 collection 类型增加 collection,对于 list 类型还会增加 list 参数,如果是 array 类型则会增加 array 参数,不过这里应用了 ifPresent,也就是如果自身参数名蕴含了则不会增加
小结
mybatis 的 ParamNameResolver 针对单个参数没有加 @Param 的场景会调用 wrapToMapIfCollection,最多会增加 collection、list、array 这些参数;其余的则多增加 param1,param2 这类参数。