关于Mybatis中为什么不需要写实现类也可以得到我们需要的对象

    科技2024-08-11  29

    比如我们需要现在需要一个方法 是查询表中的全部信息 我们会这样写

    @Override public List<User> selectAll() { SqlSession sqlSession = factory.openSession(); List<User> userList = sqlSession.selectList("com.tubai.dao.UserDao.selectAll"); sqlSession.close(); return userList; }

    主要是通过sqlSession的selectList来实现功能

    那么Mybatis是如何替我们完成这一项工作的呢?

    追寻源码

    我们通过debug模式启动 当执行到这一句的时候步入

    userDao = sqlSession.getMapper(UserDao.class);

    public <T> T getMapper(Class<T> type) { return this.configuration.getMapper(type, this); }

    next->

    public <T> T getMapper(Class<T> type, SqlSession sqlSession) { return this.mapperRegistry.getMapper(type, sqlSession); }

    ->

    public <T> T getMapper(Class<T> type, SqlSession sqlSession) { MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type); if (mapperProxyFactory == null) { throw new BindingException("Type " + type + " is not known to the MapperRegistry."); } else { try { return mapperProxyFactory.newInstance(sqlSession); } catch (Exception var5) { throw new BindingException("Error getting mapper instance. Cause: " + var5, var5); } } }

    我们发现是执行了

    return mapperProxyFactory.newInstance(sqlSession);

    继续步入->

    public T newInstance(SqlSession sqlSession) { MapperProxy<T> mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache); return this.newInstance(mapperProxy); }

    ->

    protected T newInstance(MapperProxy<T> mapperProxy) { return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{this.mapperInterface}, mapperProxy); }

    到这里我们发现是调用了动态代理的newProxyInstance方法 那么我们直接看第三个参数(是如何代理的)

    打开MapperProxy这个类

    找到里面的invoke方法

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } if (this.isDefaultMethod(method)) { return this.invokeDefaultMethod(proxy, method, args); } } catch (Throwable var5) { throw ExceptionUtil.unwrapThrowable(var5); } MapperMethod mapperMethod = this.cachedMapperMethod(method); return mapperMethod.execute(this.sqlSession, args); }

    发现它最后调用了

    mapperMethod.execute(this.sqlSession, args);

    打开这个方法的源代码继续

    public Object execute(SqlSession sqlSession, Object[] args) { Object param; Object result; switch(this.command.getType()) { case INSERT: param = this.method.convertArgsToSqlCommandParam(args); result = this.rowCountResult(sqlSession.insert(this.command.getName(), param)); break; case UPDATE: param = this.method.convertArgsToSqlCommandParam(args); result = this.rowCountResult(sqlSession.update(this.command.getName(), param)); break; case DELETE: param = this.method.convertArgsToSqlCommandParam(args); result = this.rowCountResult(sqlSession.delete(this.command.getName(), param)); break; case SELECT: if (this.method.returnsVoid() && this.method.hasResultHandler()) { this.executeWithResultHandler(sqlSession, args); result = null; } else if (this.method.returnsMany()) { result = this.executeForMany(sqlSession, args); } else if (this.method.returnsMap()) { result = this.executeForMap(sqlSession, args); } else if (this.method.returnsCursor()) { result = this.executeForCursor(sqlSession, args); } else { param = this.method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(this.command.getName(), param); } break; case FLUSH: result = sqlSession.flushStatements(); break; default: throw new BindingException("Unknown execution method for: " + this.command.getName()); } if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) { throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ")."); } else { return result; } }

    在Case:SELECT下 我们找到

    result = this.executeForMany(sqlSession, args);

    我们点开

    private <E> Object executeForMany(SqlSession sqlSession, Object[] args) { Object param = this.method.convertArgsToSqlCommandParam(args); List result; if (this.method.hasRowBounds()) { RowBounds rowBounds = this.method.extractRowBounds(args); result = sqlSession.selectList(this.command.getName(), param, rowBounds); } else { result = sqlSession.selectList(this.command.getName(), param); } if (!this.method.getReturnType().isAssignableFrom(result.getClass())) { return this.method.getReturnType().isArray() ? this.convertToArray(result) : this.convertToDeclaredCollection(sqlSession.getConfiguration(), result); } else { return result; } }~

    最终我们终于发现了

    sqlSession.selectList
    Processed: 0.012, SQL: 8