mybatis源码浅析

常用mybatis的Mapper接口形式,但是没怎么查看具体实现,抽空看了一下,

Mapper接口的动态绑定实现在 org.apache.ibatis.binding 包,该包下面有BindingException,MapperMethod,MapperProxy,MapperProxyFactory,MapperRegistry几个类。
bind

BindingException

异常类,在进行MapperBind过程中发生的异常

MapperMethod

每个MapperMethod代表一个接口方法,并且和xml标签的sql语句标签进行关联

MapperMethod有一个静态内部类SqlCommand,以及一个该类的对象,command

command

command对象指明了MapperMethod所关联的MappedStatement对象的id

(每个xml文件的insert/delete/update/select标签即对应一个MappedStatement对象)

关联方式是,command对象的name属性关联MappedStatement的Id,首先将className和methodName拼接成statementId,然后查找statementId对应的对象,如果不存在,并且接口方法和被拦截的方法的所属类是同一个,说明该接口不继承其他接口,并且没有对应的mapper实现,返回null。否则,取出所有的继承的接口,查找对应的statement。
resloveStatement

MapperProxy

实现了InvocationHandler接口,即接口方法的拦截器,
resloveStatement

invoke方法的第一个if,判断是不是Object类的方法,是则调用当前MapperProxy对象的公共方法。

invoke方法的第二个if,判断是不是接口的default方法(java8特性)

最后则是调用cachedMapperMethod方法,从缓存获取真正的MapperMethod进行调用

MapperProxyFactory,MapperRegistry

MapperProxyFactory是生成接口实现对象的真正类,

MapperRegistry则是保存 接口和接口对应的MapperProxyFactory的类。每次调用getMapper的时候,都会用MapperProxyFactory对象的newInstance生成一个新的Mapper对象

最后

Mybatis的接口和具体的Xml绑定的实现方式说到底还是jdk动态代理。我们所定义的DAO层的Mapper接口通过jdk的动态代理生成一个具体的对象;我们在用这个对象进行方法调用的时候,会通过InvocationHandler进行调用拦截,然后将DAO层接口的全限定名和方法名进行拼接,获取真正的存在于xml里面的SQL,所以xml的namespace写的是类的全限定名,而每个curd块的id是方法名。