博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MyBatis源码分析
阅读量:4655 次
发布时间:2019-06-09

本文共 4115 字,大约阅读时间需要 13 分钟。

Mybatis一般按照分析来说,可以按照三步曲进行

1、xml解析对应的配置文件

2、将配置文件通过XMLConfigBuilder解析生成Configuration对象。

3、SqlSessionFactoryBuilder通过builder方法将Configuration对象存入到里面。

4、configuration委托给MapperRegistry:运用动态代理生成对应的Dao对象.然后拿到配置文件中对应的id的sql语句,利用SqlSession执行相应的操作。

 

一般面试会问mybatis的接口是怎么实现的,其原理就是用采用jdk的动态代理来实现的,只是它的接口并没有实现类,动态代理的invoke方法中得到当前的method方法去构造MapperMethod对象,看具体代码:

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

通过mapperregistry获取对应的对象,进一步看看getMapper的代码:

public 
T getMapper(Class
type, SqlSession sqlSession) { MapperProxyFactory 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); } }}

可以看到,动态代理开始了,通过代理来产生对应的对象,但是mybatis的代理是接口的,并没有实现,不要忘记哦,来看看具体的代码:

protected T newInstance(MapperProxy
mapperProxy) { return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[]{
this.mapperInterface}, mapperProxy); //动态代理模式生成对应的类}public T newInstance(SqlSession sqlSession) { MapperProxy mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache); return this.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);        }        if(this.isDefaultMethod(method)) {            return this.invokeDefaultMethod(proxy, method, args);        }    } catch (Throwable var5) {        throw ExceptionUtil.unwrapThrowable(var5);    }     //这里去拿到对应的sql语句    MapperMethod mapperMethod = this.cachedMapperMethod(method);    return mapperMethod.execute(this.sqlSession, args);}

在来看看MapperMethod中的execute的方法:

public Object execute(SqlSession sqlSession, Object[] args) {    Object param;    Object result;    switch(null.$SwitchMap$org$apache$ibatis$mapping$SqlCommandType[this.command.getType().ordinal()]) {    case 1:        param = this.method.convertArgsToSqlCommandParam(args);        result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));        break;    case 2:        param = this.method.convertArgsToSqlCommandParam(args);        result = this.rowCountResult(sqlSession.update(this.command.getName(), param));        break;    case 3:        param = this.method.convertArgsToSqlCommandParam(args);        result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));        break;    case 4:        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 5:        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;    }}

可以看到,最终还是通过SqlSession来执行增删查改。

转载于:https://www.cnblogs.com/master-image/p/7727072.html

你可能感兴趣的文章
js技巧之this,call,apply
查看>>
angularjs学习笔记之一
查看>>
POJ2599 A funny game (图博弈)
查看>>
Android开发中无处不在的设计模式——动态代理模式
查看>>
USACO milk
查看>>
第三节《Git重置》
查看>>
面试题3,求101-200之间有多少个素数,并且输出所有素数
查看>>
@RequestBody和@RequestParam的区别
查看>>
AndroidStudio中导入module(简单版)
查看>>
OpenGL11-绘制汉字最高效方法(使用Freetype)(代码已更新)
查看>>
TP5 JSON对象数组转换为普通数组
查看>>
JMeter在linux上分布式压测环境配置(一)
查看>>
JavaScript-判断语句(if...else)
查看>>
centos7 update docker
查看>>
echarts 数据统计报表
查看>>
Android学习总结(十四) ———— ListView Item多布局的实现
查看>>
Python基础学习教程:我有故事你有酒吗?除了敲代码,程序员(媛)还能有什么副业?...
查看>>
ORA-04098错误处理
查看>>
fiddler 命令
查看>>
Learn python the eighth day
查看>>