Mybatis源码阅读之我见

作者: 遗忘的流逝 | 来源:发表于2017-04-04 15:47 被阅读488次

    今天写写mybatis,天气挺好

    先放个简单版的流程图:

    dasdf.png

    在MapperRegistry 中调用的是

    public <T> T getMapper(Class<T> type, SqlSession sqlSession)

    我们在mybatis 或者是在其他知名的框架中,基本都会有的一个操作就是动态代理,我们只命名一个接口,我们就需要实现类,而这一点全部由mybatis自己去实现。但有一点,在看源码的过程中,我发现其实我们写的接口,根本没有实现类,mybatis没有生成实现类。jdk动态代理是有一个实现类,然后实现使用类实现InvocationHandler,实现invoke方法实现切面编程。当然还有一种动态代理cglib ,这个我们就下回在讲。这个框架涉及jvm底层。
    很奇怪,但的确没有。
    这个getMapper具体流程

    mybatis.png

    到了MapperProxy<T>这个类是正在实现jdk动态代理的,我们先看一个实例成员变量 methodCache,其实我们在编程的时候有很多情况下,其实有时候用空间去换时间,是一种比较靠谱的东西。我们都知道,动态代理的时间是比较耗时的,在一定的空间允许的情况下,用缓存来存储一部分生成的method,再次询问的时候直接从map中去。缓存是用map实现的,hash原理。

    Map<Method, MapperMethod> methodCache;
    MapperMethod存储的是method的一些特性,sql语句呀等。

    我用的其实是selectOne但最终调用的是selectList这个函数。我们看源码要学到点东西,比如说这个我们从中可以体会到一点就是将不同的方法有时候可以用同一个方法进行实现,用不同的参数实现。不仅是这个函数selectMap也是用着这个方法实现的。只是用不同的方法参数进行层层叠加。
    这个框架使用了重载,将不同的默认值或者说是不同的需求回到同一个方法上。这个在很多框架上都是这样的。
    如果你有两个方法名相同参数相同的情况那么会走同一条路。MappedStatement带有一个cache对象,这个cache存在已经生成的对象,直接从缓存中取没有则从数据库中取出来。如果缓存没有的情况下最终是通过PreparedStatement进行查询。

    Mybatis的缓存分为一二两级,一级是不能指定的,是localcache, 是根据是sqlsession 为单位划分的。在sqlsession执行其他操作的时候会消失。

    二级缓存,mybatis提供了lrucache fifocache等一系列缓存机制。同样,可以实现cache这个接口来实现自己定义的cache,在配置文件中指定其cache就行了。但要注意这二级缓存的使用场景,有一个非常严重的问题如果你有其他的mapper危机是对同一张表进行操作的,那么当时的缓存并不会更新,也就是读到的是脏数据。特别注意多表操作。

    当然这种情况,存储热点数据,直接用redis等是更加稳妥的。但也有点问题就是,在用redis缓存的时候,必须要容忍一定的时间差。也就是说数据不会实时更新。

    相关文章

      网友评论

        本文标题:Mybatis源码阅读之我见

        本文链接:https://www.haomeiwen.com/subject/pytzottx.html