Mybatis 源码解析

Mybatis 源码解析,第1张

Mybatis 源码解析

文章目录
  • 前言
  • 一、SqlSessionFactoryBuilder
      • 1、build
  • 二、XMLConfigBuilder
      • 1、parse
      • 2、parseConfiguration
  • 三、DefaultSqlSessionFactory
      • 1、openSession
      • 2、getMapper
  • 四、MapperProxy
      • 1、invoke
  • 五、MapperMethod
      • 1、execute
  • 六、DefaultSqlSession
      • 1、selectList

前言
		SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
		SqlSessionFactory factory = sqlSessionFactoryBuilder.build(new FileInputStream(""));
		SqlSession sqlSession = factory.openSession();
		EmpHistoryMapper mapper = sqlSession.getMapper(EmpHistoryMapper.class);
		mapper.findHistoryEmployeeInfoById(1);

Mybais的使用流程大致如上,按如上代码逐步分析


一、SqlSessionFactoryBuilder

解析xml,实例化SessionFactory

1、build

解析XML为Cofiguration

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      // 解析XML为document
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      // 将document解析为Configuration
      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.
      }
    }
  }

 // 实例化DefaultSqlSessionFactory
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }
二、XMLConfigBuilder

解析document为Configuration

1、parse
public Configuration parse() {
	// 如果已经解析过,抛出异常
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;
    // 从configuration节点开始解析
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }
2、parseConfiguration

解析configuration节点

 try {
      //解析properties节点,并设置到configuration得variables属性
      propertiesElement(root.evalNode("properties"));
      //解析setting节点,setting节点用来设置configuration属性,如果setting的属性是configuration没有的属性,则会抛出异常
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      // 设置configuration的vfsImpl
      loadCustomVfs(settings);
      // 设置configuration的logImpl-自定义日志实现
      loadCustomLogImpl(settings);
      // 解析typeAliases节点,如果为packeage,则扫描这个包下所有的累,并注册为(类简单名称-class.simpleName,class)到typeAliasRegistry,如果是type,alias,则直接注册
      typeAliasesElement(root.evalNode("typeAliases"));
      // 解析plugins节点,并添加到configuration的interceptors
      pluginElement(root.evalNode("plugins"));
      // 解析objectFactory节点,实例化并设置到configuration的objectFacotry,objectFactory用来将查询的数据转为ResutlDTO。
      objectFactoryElement(root.evalNode("objectFactory"));
	// 解析objectWrapperFactory节点,实例化并设置到configuration的objectWrapperFactory
	objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
	// 解析reflectorFactory节点,实例化并设置到configuration的reflectorFactory
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      	// 将settings节点的内容设置到configuration,如果settings没有的属性,则设置默认值
      settingsElement(settings);
      // 解析environments节点,将节点的datasource和transactionManager封装为Enviroment并设置到configuration的environment属性
      environmentsElement(root.evalNode("environments"));
      // 解析databaseIdProvider节点,并设置configuration的databaseid为自定义获取的数据库名称
    databaseIdProviderElement(root.evalNode("databaseIdProvider"));
    // 处理typeHandlers节点,结果字段类型转换处理器
      typeHandlerElement(root.evalNode("typeHandlers"));
     // 处理mapper节点
     // 1、如果为package类型,则扫描package下的接口生产代理工厂MapperProxyFactory放入到knownMappers,并查找是否有对应的xml,有则解析xml的resultMap,mappedStatement
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
三、DefaultSqlSessionFactory 1、openSession

实例化Session

public SqlSession openSession() {
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  }

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
    // 获取执行环境
      final Environment environment = configuration.getEnvironment();
      // 获取事务工厂
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      // 获取事务
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      // 获取simple类型执行器
      final Executor executor = configuration.newExecutor(tx, execType);
      // 实例化Session
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

// 实例化Exexecutor
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
    // 如果允许使用缓存,则由CachingExecutor封装SimpleExecutor
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    // 将所有plugin封装倒executor
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }
2、getMapper

从kownMapper(前面parseConfiguration解析mapper节点),用全类名获取MapperProxyFactory,由代理工厂创建代理对象MapperProxy

// 获取代理对象
public  T getMapper(Class type) {
    return configuration.getMapper(type, this);
  }

public  T getMapper(Class type, SqlSession sqlSession) {
// 获取代理工厂
    final MapperProxyFactory mapperProxyFactory = (MapperProxyFactory) 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);
    }
  }

// 实例化代理对象
public T newInstance(SqlSession sqlSession) {
    final MapperProxy mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
    // JDK反向代理
    return newInstance(mapperProxy);
  }


四、MapperProxy

由于getMapper返回了代理对象,继而执行mapper.findHistoryEmployeeInfoById()方法时会有MapperProxy代理执行

1、invoke
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      // 对象类型为object类型,直接原方法执行
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
      // 如果改方法是public非static,非抽象(有方法body)得接口方法即为default修饰的方法,jdk代理执行
      } else if (method.isDefault()) {
        if (privateLookupInMethod == null) {
          return invokeDefaultMethodJava8(proxy, method, args);
        } else {
          return invokeDefaultMethodJava9(proxy, method, args);
        }
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
    // 实例化MapperMethod 
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    // 
    return mapperMethod.execute(sqlSession, args);
  }


// 尝试从缓存中获取MapperMethod,没有则实例化MapperMethod
private MapperMethod cachedMapperMethod(Method method) {
    return methodCache.computeIfAbsent(method,
        k -> new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
  }

// 实例化MapperMethod
 public MapperMethod(Class mapperInterface, Method method, Configuration config) {
 	// 实例化SqlCommand
    this.command = new SqlCommand(config, mapperInterface, method);
    // 实例化MethodSignature
    this.method = new MethodSignature(config, mapperInterface, method);
  }

// 实例化SqlCommand
 public SqlCommand(Configuration configuration, Class mapperInterface, Method method) {
      final String methodName = method.getName();
      final Class declaringClass = method.getDeclaringClass();
      // 根据全类名.方法名从Configuration获取MappedStatement
      MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass,
          configuration);
          //获取不到MappedStatement
      if (ms == null) {
        if (method.getAnnotation(Flush.class) != null) {
          name = null;
          type = SqlCommandType.FLUSH;
        } else {
        // 抛出找不到statement得异常
          throw new BindingException("Invalid bound statement (not found): "
              + mapperInterface.getName() + "." + methodName);
        }
      } else {
      // 设置name和type
        name = ms.getId();
        type = ms.getSqlCommandType();
        if (type == SqlCommandType.UNKNOWN) {
          throw new BindingException("Unknown execution method for: " + name);
        }
      }
    }

// 实例化MethodSignature 方法签名
public MethodSignature(Configuration configuration, Class mapperInterface, Method method) {
	  // 返回类型--处理泛型、数组元素类型
      Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
      if (resolvedReturnType instanceof Class) {
        this.returnType = (Class) resolvedReturnType;
      } else if (resolvedReturnType instanceof ParameterizedType) {
        this.returnType = (Class) ((ParameterizedType) resolvedReturnType).getRawType();
      } else {
        this.returnType = method.getReturnType();
      }
      // 返回类型是否void
      this.returnsVoid = void.class.equals(this.returnType);
      // 返回类型是否集合
      this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
       // 返回类型是否Cursor
      this.returnsCursor = Cursor.class.equals(this.returnType);
      // 返回类型是否Optional
      this.returnsOptional = Optional.class.equals(this.returnType);
      // 解析MapKey注解
      this.mapKey = getMapKey(method);
      // 是否有returnsMap 
      this.returnsMap = this.mapKey != null;
      // 获取类型为RowBounds得参数得索引下标--Page实现了RowBounds
      this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
       // 获取类型为ResultHandler得参数得索引下标
      this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
      // 实例化ParamNameResolver
      this.paramNameResolver = new ParamNameResolver(configuration, method);
    }

 // 实例化ParamNameResolver
public ParamNameResolver(Configuration config, Method method) {
	// 获取方法所有参数类型
    final Class[] paramTypes = method.getParameterTypes();
    // 获取方法所有参数注解
    final Annotation[][] paramAnnotations = method.getParameterAnnotations();
    final SortedMap map = new TreeMap<>();
    // 参数个数
    int paramCount = paramAnnotations.length;
    // get names from @Param annotations-处理被@Param注解得参数
    for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
    	// 跳过RowBounds和ResultHandler
      if (isSpecialParameter(paramTypes[paramIndex])) {
        // skip special parameters
        continue;
      }
      String name = null;
      // 遍历所有注解
      for (Annotation annotation : paramAnnotations[paramIndex]) {
      	// 注解为Param
        if (annotation instanceof Param) {
          // 标记hasParamAnnotation为true
          hasParamAnnotation = true;
          // 设置name为Param的value,参数名称
          name = ((Param) annotation).value();
          break;
        }
      }
      if (name == null) {
        // @Param was not specified. -- 设置name获取参数名称
        if (config.isUseActualParamName()) {
          name = getActualParamName(method, paramIndex);
        }
        if (name == null) {
          // use the parameter index as the name ("0", "1", ...)
          // 设置为当前map大小
          // gcode issue #71
          name = String.valueOf(map.size());
        }
      }
      // map<参数索引,参数名称> name可能为Param的value,方法参数名称,数字
      map.put(paramIndex, name);
    }
    // names <参数索引,参数名称>
    names = Collections.unmodifiableSortedMap(map);
  }
五、MapperMethod

1、execute

解析执行sql

public Object execute(SqlSession sqlSession, Object[] args) {
    Object result;
    switch (command.getType()) {
      .....
      // select语句,以下只分析executeForMany
      case SELECT:
        if (method.returnsVoid() && method.hasResultHandler()) {
          executeWithResultHandler(sqlSession, args);
          result = null;
        } else if (method.returnsMany()) { // 返回结果为集合
          result = executeForMany(sqlSession, args);
        } else if (method.returnsMap()) {// 返回结果为Map
          result = executeForMap(sqlSession, args);
        } else if (method.returnsCursor()) {
          result = executeForCursor(sqlSession, args);
        } else {
          Object param = method.convertArgsToSqlCommandParam(args);
          result = sqlSession.selectOne(command.getName(), param);
          if (method.returnsOptional()
              && (result == null || !method.getReturnType().equals(result.getClass()))) {
            result = Optional.ofNullable(result);
          }
        }
        break;
      case FLUSH:
        result = sqlSession.flushStatements();
        break;
      default:
        throw new BindingException("Unknown execution method for: " + command.getName());
    }
    if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
      throw new BindingException("Mapper method '" + command.getName()
          + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
    }
    return result;
  }

// 处理返回类型为集合的sql
private  Object executeForMany(SqlSession sqlSession, Object[] args) {
    List result;
    // 封装参数中的变量#{name}
    Object param = method.convertArgsToSqlCommandParam(args);
    // 参数是否RowBounds-Page
    if (method.hasRowBounds()) {
     // 获取参数RowBounds
      RowBounds rowBounds = method.extractRowBounds(args);
      // 准备执行查询
      result = sqlSession.selectList(command.getName(), param, rowBounds);
    } else {
      result = sqlSession.selectList(command.getName(), param);
    }
    // issue #510 Collections & arrays support
    if (!method.getReturnType().isAssignableFrom(result.getClass())) {
      if (method.getReturnType().isArray()) {
        return convertToArray(result);
      } else {
        return convertToDeclaredCollection(sqlSession.getConfiguration(), result);
      }
    }
    return result;
  }

// 封装参数中的变量#{name}使用的参数个数
    final int paramCount = names.size();
    // 无参
    if (args == null || paramCount == 0) {
      return null;
      // 有Param注解的参数并且参数个数为一个
    } else if (!hasParamAnnotation && paramCount == 1) {
    // 直接返回第一个参数
      return args[names.firstKey()];
    } else {
    // 实例化参数Map<参数名称,值> 参数名称name可能为Param的value,方法参数名称,数字,或者param1(2.3)
      final Map param = new ParamMap<>();
      int i = 0;
      for (Map.Entry entry : names.entrySet()) {
      	// 参数名称,参数值
        param.put(entry.getValue(), args[entry.getKey()]);
        // add generic param names (param1, param2, ...)
        // 另一套键值对 param1 , value
        final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
        // ensure not to overwrite parameter named with @Param
        // 判断names是否已经有 param1,确保不覆盖@Param
        if (!names.containsValue(genericParamName)) {
          param.put(genericParamName, args[entry.getKey()]);
        }
        i++;
      }
      return param;
    }
  }

六、DefaultSqlSession

会话

1、selectList

执行返回结果为集合的查询

public  List selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      // 获取对应的MappedStatement
      MappedStatement ms = configuration.getMappedStatement(statement);
      // 由Executor执行查询,这一块本身有缓存的话Executor会被CachingExecutor封装,由于基本不开启缓存,所以从SimpleExecutor分析
      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();
    }
  }

// 处理只有一个参数类型为集合并且没有@Param的情
// Collection 
// Array 
 private Object wrapCollection(final Object object) {
    if (object instanceof Collection) {
      StrictMap map = new StrictMap<>();
      map.put("collection", object);
      if (object instanceof List) {
        map.put("list", object);
      }
      return map;
    } else if (object != null && object.getClass().isArray()) {
      StrictMap map = new StrictMap<>();
      map.put("array", object);
      return map;
    }
    return object;
  }
					
										


					

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5684852.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)