Mybatis 调用过程源码分析

Posted 测开精进之路

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis 调用过程源码分析相关的知识,希望对你有一定的参考价值。

Mybatis在调用过程中,主要分为三块:

  • 生成DefaultSqlSessionFactory

  • 生成代理类

  • 利用代理类进行方法调用


一、生成DefaultSqlSessionFactory

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { //解析mapper文件中的结构 XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); return build(parser.parse()); } catch (Exception e) { throw ExceptionFactory.wrapException("Error building SqlSession.", e); } finally { ErrorContext.instance().reset(); try { inputStream.close(); } catch (IOException e) { // Intentionally ignore. Prefer previous error. } }}

二、生成代理类

Mybatis 调用过程源码分析

通过动态代理,生成接口的实现类

1:DefaultSqlSession

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

2:Configration

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

3:MapperRegistry

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

4:MapperProxy

protected T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);}public T newInstance(SqlSession sqlSession) { final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache); return newInstance(mapperProxy);}protected T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);}public T newInstance(SqlSession sqlSession) { final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache); return newInstance(mapperProxy);}

三、利用代理类进行调用

在具体调用过程中:

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

在MapperMethod中判断接口的类型(insert;update;delete),再调用sqlsession进行调用

public Object execute(SqlSession sqlSession, Object[] args) { 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; }…….


在sqlsession 调用过程中,通过MappedStatement,和传入的参数,动态生成执行sql

@Overridepublic <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { try { MappedStatement ms = configuration.getMappedStatement(statement); return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); }}
@Overridepublic <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { BoundSql boundSql = ms.getBoundSql(parameter); CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql); return query(ms, parameter, rowBounds, resultHandler, key, boundSql);}

以上就是整个调用过程。 


以上是关于Mybatis 调用过程源码分析的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis实现与插件开发

精尽MyBatis源码分析 - SQL执行过程之 StatementHandler

Mybatis源码分析

mybatis源码学习:基于动态代理实现查询全过程

MyBatis源码分析-IDEA新建MyBatis源码工程

MyBatis源码分析-IDEA新建MyBatis源码工程