mybatis原始碼reflection包--引數解析器ParamNameResolver
阿新 • • 發佈:2021-01-04
技術標籤:# mybatis基礎包原始碼
ParamNameResolver是一個引數名解析器,負責把方法的引數按順序解析出來並進行標註。
1.因為設計到字串處理,隨便寫一個方法進行debug跟蹤
ParamNameResolver在構造器中對getUserInfo進行解析,邏輯很簡單,獲取該方法所有引數型別進行遍歷,如果該引數上有@Param註解就獲取Param中的value作為屬性名,沒有的話就判斷配置中useActualParamName是否允許使用原始引數名,不允許就用引數順序進行命名。最後把解析結果存到ParamNameResolver的names屬性中。
// 方法入參的引數次序表。鍵為引數次序,值為引數名稱或者引數@Param註解的值 private final SortedMap<Integer, String> names; // 該方法入參中是否含有@Param註解 private boolean hasParamAnnotation; /** * 引數名解析器的構造方法 * @param config 配置資訊 * @param method 要被分析的方法 */ public ParamNameResolver(Configuration config, Method method) { // 獲取引數型別列表 final Class<?>[] paramTypes = method.getParameterTypes(); // 準備存取所有引數的註解,是二維陣列 final Annotation[][] paramAnnotations = method.getParameterAnnotations(); final SortedMap<Integer, String> map = new TreeMap<>(); int paramCount = paramAnnotations.length; // 迴圈處理各個引數 for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) { if (isSpecialParameter(paramTypes[paramIndex])) { // 跳過特別的引數 continue; } // 引數名稱 String name = null; for (Annotation annotation : paramAnnotations[paramIndex]) { // 找出引數的註解 if (annotation instanceof Param) { // 如果註解是Param hasParamAnnotation = true; // 那就以Param中值作為引數名 name = ((Param) annotation).value(); break; } } if (name == null) { // 否則,保留引數的原有名稱 if (config.isUseActualParamName()) { name = getActualParamName(method, paramIndex); } if (name == null) { // 引數名稱取不到,則按照引數index命名 name = String.valueOf(map.size()); } } map.put(paramIndex, name); } names = Collections.unmodifiableSortedMap(map); }
debug跟蹤後 names的結果如下:
2.ParamNameResolver的getNamedParams函式是在確定names屬性後,給出方法引數名->引數值的對映
原始碼如下:
public Object getNamedParams(Object[] args) { final int paramCount = names.size(); if (args == null || paramCount == 0) { return null; } else if (!hasParamAnnotation && paramCount == 1) { return args[names.firstKey()]; } else { final Map<String, Object> param = new ParamMap<>(); int i = 0; for (Map.Entry<Integer, String> entry : names.entrySet()) { // 首先按照類註釋中提供的key,存入一遍 【引數的@Param名稱 或者 引數排序:實參值】 // 注意,key和value交換了位置 param.put(entry.getValue(), args[entry.getKey()]); // add generic param names (param1, param2, ...) final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1); // ensure not to overwrite parameter named with @Param // 再按照param1, param2, ...的命名方式存入一遍 if (!names.containsValue(genericParamName)) { param.put(genericParamName, args[entry.getKey()]); } i++; } return param; } }
假設對上邊自己定義的介面呼叫
getUserInfo(1,18,"波多野結衣")
debug跟蹤他返回的結果是: