美文网首页
MyBatis-Mapper动态代理

MyBatis-Mapper动态代理

作者: GIT提交不上 | 来源:发表于2020-03-20 18:14 被阅读0次

    MyBatis官方教程
    MyBatis二级缓存设计
    Mybatis中Mapper动态代理的实现原理
    制作Mybatis插件---针对Mybatis的四大对象

      调用SqlSession的getMapper方法 <==> MapperRegistry的getMapper方法(注册Mapper接口与获取生成代理类实例的工具类)。

        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 {
                    //获取MapperProxy对象
                    return mapperProxyFactory.newInstance(sqlSession);
                } catch (Exception var5) {
                    throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
                }
            }
        }
    
    

      MapperProxy类构造方法:

      //sqlSession & 接口 & 接口方法
       public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
            this.sqlSession = sqlSession;
            this.mapperInterface = mapperInterface;
            this.methodCache = methodCache;
        }
    

      MapperProxy类invoke方法:从缓存中获得执行方法对应的MapperMethod类实例;如果MapperMethod类实例不存在的情况,创建加入缓存并返回相关的实例。

       //接口代理对象所有的方法调用都会调用该方法
       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            try {
                if (Object.class.equals(method.getDeclaringClass())) {
                    return method.invoke(this, args);
                }
    
                if (method.isDefault()) {
                    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类构造方法:SqlCommand & MethodSignature(说明方法的一些信息)。

      public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
            this.command = new MapperMethod.SqlCommand(config, mapperInterface, method);
            this.method = new MapperMethod.MethodSignature(config, mapperInterface, method);
        }
    

      SqlCommand来封装底层的增删改查操作,MappedStatement的resource对应xml路径,id对应接口名+方法名。

    图1-1 MappedStatement结构.png

      MappedStatement创建:在SqlSessionFactory创建时,SqlSessionFactoryBuilder类build方法。MapperBuilderAssistant类的addMappedStatement方法。

    图1-2 MappedStatement创建堆栈信息.png

      MapperMethod类execute方法部分源码:

    public Object execute(SqlSession sqlSession, Object[] args) {
            Object result;
            Object param;
            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;
    
    图1-3 缓存.png 图1-4 查询流程.png

    补充知识:四大对象 & 插件拦截 & 分页插件 & 批量执行 & 存储过程 & 自定义类型处理器(处理枚举)

    相关文章

      网友评论

          本文标题:MyBatis-Mapper动态代理

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