MyBatis創建動態代理類源碼流程

總結

調用的getMapper方法(1)調用ConfigurationgetMapper方法(2)調用MapperRegistrygetMapper方法(3)調用MapperProxyFactory的newInstance方法(4)調用兄弟newInstance方法(6)使用動態代理模式去設置mapperProxy爲目標Dao方法的代理(7),MapperProxy這個類中的invoke實現是利用MapperMethod的execute來執行的(19)

源碼片段

已省略部分細節,只保留了主要方法調用。上文的括號中數字對應源碼行數。

sqlSession.getMapper(){//去DefaultSqlSession
    return configuraion.<T>getMapper(type,this) {//去Configuration.java
        return mapperRegistry.getMapper(type, sqlSession) {//去MapperRegistry.java
            return mapperProxyFactory.newInstance(sqlSession){//去MapperProxyFactory.java
                final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
                return newInstance(mapperProy) {//兄弟方法
                    return (T)Proxy.newProxyInstance(mapperInterface.getClassLoader(),new Class[]{mapperInterface},mapperProxy/*加強Dao接口的代理類MapperProxy的對象*/))
                }
            }
        }
    }
}

class MapperProxy<T> implements InvocationHandler, Serializable{
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
        ...
        final MapperMethod mapperMethod = cacheMapperMethod(method);
        return mapperMethod.execute(sqlSession, args){//去MapperMethod.java
            Object result;
            switch (command.getType()) {
              case INSERT: {
               Object param = method.convertArgsToSqlCommandParam(args);
                result = rowCountResult(sqlSession.insert(command.getName(), param));
                break;
              }
              case UPDATE: {
                Object param = method.convertArgsToSqlCommandParam(args);
                result = rowCountResult(sqlSession.update(command.getName(), param));
                break;
              }
              case DELETE: {
                Object param = method.convertArgsToSqlCommandParam(args);
                result = rowCountResult(sqlSession.delete(command.getName(), param));
                break;
              }
              case SELECT:
                if (method.returnsVoid() && method.hasResultHandler()) {
                  executeWithResultHandler(sqlSession, args);
                  result = null;
                } else if (method.returnsMany()) {
                  result = executeForMany(sqlSession, args);
                } else if (method.returnsMap()) {
                  result = executeForMap(sqlSession, args);
                } else if (method.returnsCursor()) {
                  result = executeForCursor(sqlSession, args);
                } else {
                  Object param = method.convertArgsToSqlCommandParam(args);
                  result = sqlSession.selectOne(command.getName(), param);
                }
                break;
              case FLUSH:
                result = sqlSession.flushStatements();
                break;
              default:
                throw new BindingException("Unknown execution method for: " + command.getName());
            }
            if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
              throw new BindingException("Mapper method '" + command.getName() 
                  + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
            }
            return result;            
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章