我是靠谱客的博主 缓慢音响,最近开发中收集的这篇文章主要介绍mybatis源码解析九之整个加载流程解析加载Reader构造SqlSessionFactoryopenSessiongetMapper调用mapper反射缓存解析crud,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • 加载Reader
  • 构造SqlSessionFactory
    • 获取Document
    • Configuration初始化
    • 解析Xnode
      • 解析Attributes
      • 解析占位符
      • 解析标签内容
    • 解析Configuration
      • 解析properties
      • 解析settings
      • 解析typeAliases
      • 解析plugins
      • 解析objectFactory
      • 解析environments
      • 解析databaseIdProvider
      • 解析typeHandlers
      • 解析mappers
        • 扫描包 todo
        • 解析resource|url
          • 解析mapper
            • 解析crud|cache|cache-ref
            • 解析resultMap
            • 解析sql
          • 注册mapper
    • buildSqlSessionFactory
  • openSession
    • 根据配置创建Executor 对象
      • 插件支持
  • getMapper
  • 调用mapper
    • 执行调用
      • C
      • R
        • 创建Statement 对象
        • 处理占位符
        • 查询以及处理结果集
        • 一级缓存
        • 对二级缓存的支持
  • 反射
    • 查找clazz 的默认构造方法(无参构造方法)
    • 处理clazz 中的getter 方法
    • 处理clazz 中的setter 方法
    • 处理没有getter setter 方法的字段
  • 缓存
    • 一级缓存
    • 二级缓存
      • cache-ref
      • cache
  • 解析crud
    • 解析<include> 节点
    • 解析<selectKey> 节点

demo地址

 public static void main(String[] args) throws Exception {
        Reader reader = Resources.getResourceAsReader("mybatis/SqlMapconfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
/*            User user = new User(1L, "哈哈", "哈哈");
            mapper.insertUser(user);
            sqlSession.commit();*/

            User user1 = mapper.getUser(24);
            System.out.println(user1);
        } finally {
            sqlSession.close();
        }

    }

加载Reader

  public static Reader getResourceAsReader(String resource) throws IOException {
    Reader reader;
    if (charset == null) {
      reader = new InputStreamReader(getResourceAsStream(resource));
    } else {
      reader = new InputStreamReader(getResourceAsStream(resource), charset);
    }
    return reader;
  }

  public static InputStream getResourceAsStream(String resource) throws IOException {
    return getResourceAsStream(null, resource);
  }
  public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
    InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
    if (in == null) {
      throw new IOException("Could not find resource " + resource);
    }
    return in;
  }
  public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
    return getResourceAsStream(resource, getClassLoaders(classLoader));
  }
/**
   * 返回Class Loader[]数组,该数组指明了类加载器的使用顺序
   * @param classLoader
   * @return
   */
  ClassLoader[] getClassLoaders(ClassLoader classLoader) {
    return new ClassLoader[]{
      //参数指定的类加载器
      classLoader,
      //系统指定的默认类加载器
      defaultClassLoader,
      // 当前线程绑定的类加载器
      Thread.currentThread().getContextClassLoader(),
      // 加载当前类所使用的类加载器
      getClass().getClassLoader(),
      //System Cl assLoader
      systemClassLoader};
  }

构造SqlSessionFactory

  public SqlSessionFactory build(Reader reader) {
    return build(reader, null, null);
  }
 public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        reader.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }
  public XMLConfigBuilder(Reader reader, String environment, Properties props) {
    this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
  }
  public XPathParser(Reader reader, boolean validation, Properties variables, EntityResolver entityResolver) {
    commonConstructor(validation, variables, entityResolver);
    this.document = createDocument(new InputSource(reader));
  }
  private void commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver) {
    this.validation = validation;
    this.entityResolver = entityResolver;
    this.variables = variables;
    XPathFactory factory = XPathFactory.newInstance();
    this.xpath = factory.newXPath();
  }

获取Document

private Document createDocument(InputSource inputSource) {
    // important: this must only be called AFTER common constructor
    try {
      // 创建工厂
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
      factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
      factory.setValidating(validation);

      factory.setNamespaceAware(false);
      factory.setIgnoringComments(true);
      factory.setIgnoringElementContentWhitespace(false);
      factory.setCoalescing(false);
      factory.setExpandEntityReferences(true);
      // 得到dom解析器
      DocumentBuilder builder = factory.newDocumentBuilder();
      //设置DTD解析器
      builder.setEntityResolver(entityResolver);
      builder.setErrorHandler(new ErrorHandler() {
        @Override
        public void error(SAXParseException exception) throws SAXException {
          throw exception;
        }

        @Override
        public void fatalError(SAXParseException exception) throws SAXException {
          throw exception;
        }

        @Override
        public void warning(SAXParseException exception) throws SAXException {
          // NOP
        }
      });
      //加载XML
      return builder.parse(inputSource);
    } catch (Exception e) {
      throw new BuilderException("Error creating document instance.  Cause: " + e, e);
    }
  }
  @Override
  public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
    try {
      if (systemId != null) {
        String lowerCaseSystemId = systemId.toLowerCase(Locale.ENGLISH);
        //查找sysId指定的DTD文档,并读取
        if (lowerCaseSystemId.contains(MYBATIS_CONFIG_SYSTEM) || lowerCaseSystemId.contains(IBATIS_CONFIG_SYSTEM)) {
          return getInputSource(MYBATIS_CONFIG_DTD, publicId, systemId);
        } else if (lowerCaseSystemId.contains(MYBATIS_MAPPER_SYSTEM) || lowerCaseSystemId.contains(IBATIS_MAPPER_SYSTEM)) {
          return getInputSource(MYBATIS_MAPPER_DTD, publicId, systemId);
        }
      }
      return null;
    } catch (Exception e) {
      throw new SAXException(e.toString());
    }
  }
  private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
    super(new Configuration());
    ErrorContext.instance().resource("SQL Mapper Configuration");
    this.configuration.setVariables(props);
     //标记没有解析过mybatis-config.xml 配置文件
    this.parsed = false;
    this.environment = environment;
    //设置Xpath
    this.parser = parser;
  }

Configuration初始化

  public Configuration() {
    //注册别名
    typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
    typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);

    typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
    typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
    typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);

    typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
    typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
    typeAliasRegistry.registerAlias("LRU", LruCache.class);
    typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
    typeAliasRegistry.registerAlias("WEAK", WeakCache.class);

    typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);

    typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
    typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);

    typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
    typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
    typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
    typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
    typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
    typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
    typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);

    typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
    typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
//将XmlLanguageDriver 设置为默认的动态SQL 语言驱动器
    languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
    languageRegistry.register(RawLanguageDriver.class);
  }

  public Configuration parse() {
    if (parsed) {
      throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    parsed = true;//标记已经解析xml配置文件configuration标签
    //在mybatis-config.xml 配置文件中查找< configuration >节点,并开始解析
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
  }

解析Xnode

  public XNode evalNode(String expression) {
    return evalNode(document, expression);
  }
  public XNode evalNode(Object root, String expression) {
    Node node = (Node) evaluate(expression, root, XPathConstants.NODE);//xpath解析
    if (node == null) {
      return null;
    }
    return new XNode(this, node, variables);
  }
  public XNode(XPathParser xpathParser, Node node, Properties variables) {
    this.xpathParser = xpathParser;
    this.node = node;
    this.name = node.getNodeName();//设置节点名
    this.variables = variables;
    this.attributes = parseAttributes(node);//获取标签里面设置的属性
    this.body = parseBody(node);//解析<config>标签里面的内容
  }

解析Attributes

 private Properties parseAttributes(Node n) {
    Properties attributes = new Properties();
    //获取节点的属性集合
    NamedNodeMap attributeNodes = n.getAttributes();
    if (attributeNodes != null) {
      for (int i = 0; i < attributeNodes.getLength(); i++) {
        Node attribute = attributeNodes.item(i);
        //使用PropertyParser 处理每个属性中的占位符
        String value = PropertyParser.parse(attribute.getNodeValue(), variables);
        attributes.put(attribute.getNodeName(), value);
      }
    }
    return attributes;
  }

解析占位符

  public static String parse(String string, Properties variables) {
    VariableTokenHandler handler = new VariableTokenHandler(variables);
    //指定处理的占位符格式为${}
    GenericTokenParser parser = new GenericTokenParser("${", "}", handler);
    return parser.parse(string);
  }
 /**
   * 将text根据前后占位符解析
   * @param text
   * @return
   */
  public String parse(String text) {
    if (text == null || text.isEmpty()) {
      return "";
    }
    // search open token
    //查找第一个开启占位符位置
    int start = text.indexOf(openToken);
    if (start == -1) {
      return text;
    }
    char[] src = text.toCharArray();
    int offset = 0;
    //线程安全,记录占位符的值
    final StringBuilder builder = new StringBuilder();
    StringBuilder expression = null;
    while (start > -1) {
      if (start > 0 && src[start - 1] == '\') {
        // this open token is escaped. remove the backslash and continue.
        //遇到转义的开始标记,直接将前面的字符串以及开始标记追加
        builder.append(src, offset, start - offset - 1).append(openToken);
        offset = start + openToken.length();
      } else {
        // found open token. let's search close token.
        //查找到开始标记,且未转义
        if (expression == null) {
          expression = new StringBuilder();
        } else {
          expression.setLength(0);
        }
        //前面字符追加
        builder.append(src, offset, start - offset);
        offset = start + openToken.length();
        //从offset后继续查找结束标记
        int end = text.indexOf(closeToken, offset);
        while (end > -1) {
          if (end > offset && src[end - 1] == '\') {
            // this close token is escaped. remove the backslash and continue.
            //处理转义的结束标记
            expression.append(src, offset, end - offset - 1).append(closeToken);
            offset = end + closeToken.length();
            end = text.indexOf(closeToken, offset);
          } else {
            //将开始标记和结束标记之间字符添加
            expression.append(src, offset, end - offset);
            break;
          }
        }
        if (end == -1) {
          //未找到结束标记
          // close token was not found.
          builder.append(src, start, src.length - start);
          offset = src.length;
        } else {
          //将占位符的值交给handler处理,并保存builder
          builder.append(handler.handleToken(expression.toString()));
          offset = end + closeToken.length();
        }
      }
      //移动start
      start = text.indexOf(openToken, offset);
    }
    if (offset < src.length) {
      builder.append(src, offset, src.length - offset);
    }
    return builder.toString();
  }
   @Override
    public String handleToken(String content) {
      //variables非空
      if (variables != null) {
        String key = content;
        //是否支持占位符中使用默认值功能
        if (enableDefaultValue) {
          //查找分割符
          final int separatorIndex = content.indexOf(defaultValueSeparator);
          String defaultValue = null;
          if (separatorIndex >= 0) {
            //获取占位符名称
            key = content.substring(0, separatorIndex);
            //获取默认值
            defaultValue = content.substring(separatorIndex + defaultValueSeparator.length());
          }
          if (defaultValue != null) {
            //查找指定占位符
            return variables.getProperty(key, defaultValue);
          }
        }
        //不支持默认值,则直接找
        if (variables.containsKey(key)) {
          return variables.getProperty(key);
        }
      }
      //variables空
      return "${" + content + "}";
    }
  }

解析标签内容

  private String parseBody(Node node) {
    //获取标签内容,且解析${}占位符里面的值
    String data = getBodyData(node);
    //当前节点不是文本节点
    if (data == null) {
      NodeList children = node.getChildNodes();
      for (int i = 0; i < children.getLength(); i++) {
        Node child = children.item(i);
        data = getBodyData(child);
        if (data != null) {
          break;
        }
      }
    }
    return data;
  }
    private String getBodyData(Node child) {
    //只处理文本内容
    if (child.getNodeType() == Node.CDATA_SECTION_NODE
        || child.getNodeType() == Node.TEXT_NODE) {
      String data = ((CharacterData) child).getData();
      //使用PropertyParser 处理文本节点中的占位符
      data = PropertyParser.parse(data, variables);
      return data;
    }
    return null;
  }

解析Configuration

 private void parseConfiguration(XNode root) {
    try {
      // issue #117 read properties first
      //解析<properties>节点
      propertiesElement(root.evalNode("properties"));
      //解析<settings>节点
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      //设置vfsimpl 字段
      loadCustomVfs(settings);
      loadCustomLogImpl(settings);
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      settingsElement(settings);
      // read it after objectFactory and objectWrapperFactory issue #631
      //每个<environment> 节点对应一种环境的配置。
      environmentsElement(root.evalNode("environments"));
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlerElement(root.evalNode("typeHandlers"));
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }

解析properties

private void propertiesElement(XNode context) throws Exception {
    if (context != null) {
      //解析<properties >的子节点(<property>标签)的name 和value 属性,并记录到Properties 中
      Properties defaults = context.getChildrenAsProperties();
      //解析< properties >的resource 和url ,这两个属性用于确定properties 配置文件的位置
      String resource = context.getStringAttribute("resource");
      String url = context.getStringAttribute("url");
    //resource 属性和url 属性不能同时存在,否则会抛出异常
      if (resource != null && url != null) {
        throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference.  Please specify one or the other.");
      }
      //加载resource或url
      if (resource != null) {
        defaults.putAll(Resources.getResourceAsProperties(resource));
      } else if (url != null) {
        defaults.putAll(Resources.getUrlAsProperties(url));
      }
      //与configuration对象中的variables集合合并
      Properties vars = configuration.getVariables();
      if (vars != null) {
        defaults.putAll(vars);
      }
      //更新XPathParser和Configuration的variables字段
      parser.setVariables(defaults);
      configuration.setVariables(defaults);
    }
  }

在这里插入图片描述

解析settings

  private Properties settingsAsProperties(XNode context) {
    if (context == null) {
      return new Properties();
    }
    //解析< settings >的子节点(< setting >标签)的name 和value 属性,并返回Properties 对象
    Properties props = context.getChildrenAsProperties();
    // Check that all settings are known to the configuration class
    //创建Configurat对应的MetaClass 对象
    MetaClass metaConfig = MetaClass.forClass(Configuration.class, localReflectorFactory);
    //检测Configuration 中是否定义了key 指定属性相应的setter 方法
    for (Object key : props.keySet()) {
      if (!metaConfig.hasSetter(String.valueOf(key))) {
        throw new BuilderException("The setting " + key + " is not known.  Make sure you spelled it correctly (case sensitive).");
      }
    }
    return props;
  }
 private void settingsElement(Properties props) {
    configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));
    configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));
    configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));
    configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory")));
    configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));
    configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), false));
    configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));
    configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));
    configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));
    configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE")));
    configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null));
    configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null));
    configuration.setDefaultResultSetType(resolveResultSetType(props.getProperty("defaultResultSetType")));
    configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false));
    configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false));
    configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION")));
    configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER")));
    configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString"));
    configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));
    configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage")));
    configuration.setDefaultEnumTypeHandler(resolveClass(props.getProperty("defaultEnumTypeHandler")));
    configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));
    configuration.setUseActualParamName(booleanValueOf(props.getProperty("useActualParamName"), true));
    configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));
    configuration.setLogPrefix(props.getProperty("logPrefix"));
    configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));
  }

解析typeAliases

 private void typeAliasesElement(XNode parent) {
    if (parent != null) {
      //处理全部子节点
      for (XNode child : parent.getChildren()) {
        //处理< package >节点
        if ("package".equals(child.getName())) {
          // 获取指定的包名
          String typeAliasPackage = child.getStringAttribute("name");
          //通过TypeAliasRegistry 扫描指定包中所有的类,并解析@ Alias注解,完成别名注册
          configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);
        } else {
          //处理< typeAlias >节点
          String alias = child.getStringAttribute("alias");
          String type = child.getStringAttribute("type");
          try {
            Class<?> clazz = Resources.classForName(type);
            if (alias == null) {
             //  扫描@Alias注解,完成注册
              typeAliasRegistry.registerAlias(clazz);
            } else {
              // 注册别名
              typeAliasRegistry.registerAlias(alias, clazz);
            }
          } catch (ClassNotFoundException e) {
            throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e);
          }
        }
      }
    }
  }

解析plugins

 private void pluginElement(XNode parent) throws Exception {
    if (parent != null) {
      //追历全部子节点(即< plugin>节点)
      for (XNode child : parent.getChildren()) {
        //获取<plugin>节点的interceptor 属性的值
        String interceptor = child.getStringAttribute("interceptor");
        //获取<plugin>节点下<properties>配置的信息,并形成Properties 对象
        Properties properties = child.getChildrenAsProperties();
        //通过前面介绍的TypeAliasRegistry 解析别名之后,实例化Interceptor 对象
        Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).getDeclaredConstructor().newInstance();
        // 设置Interceptor 的属性
        interceptorInstance.setProperties(properties);
        // 记录Interceptor 对象
        configuration.addInterceptor(interceptorInstance);
      }
    }
  }
 protected <T> Class<? extends T> resolveClass(String alias) {
    if (alias == null) {
      return null;
    }
    try {
      return resolveAlias(alias);
    } catch (Exception e) {
      throw new BuilderException("Error resolving class. Cause: " + e, e);
    }
  }

  protected <T> Class<? extends T> resolveAlias(String alias) {
    return typeAliasRegistry.resolveAlias(alias);
  }
 public <T> Class<T> resolveAlias(String string) {
    try {
      if (string == null) {
        return null;
      }
      // issue #748
      String key = string.toLowerCase(Locale.ENGLISH);
      Class<T> value;
      if (typeAliases.containsKey(key)) {
        value = (Class<T>) typeAliases.get(key);
      } else {
        value = (Class<T>) Resources.classForName(string);
      }
      return value;
    } catch (ClassNotFoundException e) {
      throw new TypeException("Could not resolve type alias '" + string + "'.  Cause: " + e, e);
    }
  }
  public void addInterceptor(Interceptor interceptor) {
    interceptorChain.addInterceptor(interceptor);
  }

  public void addInterceptor(Interceptor interceptor) {
    interceptors.add(interceptor);
  }

解析objectFactory

 private void objectFactoryElement(XNode context) throws Exception {
    if (context != null) {
      //获取<objectFactory> 节点的type 属性
      String type = context.getStringAttribute("type");
      //获取<objectFactory>节点下配置的信息,并形成Properties对象
      Properties properties = context.getChildrenAsProperties();
      //进行别名解析后,实例化自定义ObjectFactory实现
      ObjectFactory factory = (ObjectFactory) resolveClass(type).getDeclaredConstructor().newInstance();
      //设置自定义ObjectFactory 的属性,完成初始化的相关操作
      factory.setProperties(properties);
      //将自定义ObjectFactory 对象记录到configuration对象的objectFactory 字段中,待后续使用
      configuration.setObjectFactory(factory);
    }
  }

解析environments

  private void environmentsElement(XNode context) throws Exception {
    if (context != null) {
      //未指定XMLConfigBuilder.environment 字段,则使用default属性指定的< environment>
      if (environment == null) {
        environment = context.getStringAttribute("default");
      }
      //遍历子节点(即< environment > 节点)
      for (XNode child : context.getChildren()) {
        String id = child.getStringAttribute("id");
        //与XMLConfigBuilder.environment匹配
        if (isSpecifiedEnvironment(id)) {
          //创建TransactionFactory ,具体实现是先通过TypeAliasRegistry 解析别名之后,实例化
          TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
          //创建DataSourceFactory 和DataSource
          DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
          DataSource dataSource = dsFactory.getDataSource();
           //创建Environment, Environment 中封装了上面创建的TransactionFactory 对象 以及DataSource 对象。这里应用了建造者模式
          Environment.Builder environmentBuilder = new Environment.Builder(id)
              .transactionFactory(txFactory)
              .dataSource(dataSource);
           //将Environment 对象记录到Configuration.environment 字段中
          configuration.setEnvironment(environmentBuilder.build());
        }
      }
    }
  }

其他过程非常简单就不贴出来了

解析databaseIdProvider

 private void databaseIdProviderElement(XNode context) throws Exception {
    DatabaseIdProvider databaseIdProvider = null;
    if (context != null) {
      String type = context.getStringAttribute("type");
      // awful patch to keep backward compatibility
      //为了保证兼容性,修改type 取值
      if ("VENDOR".equals(type)) {
        type = "DB_VENDOR";
      }
      Properties properties = context.getChildrenAsProperties();
      //创建DatabaseidProvider 对象
      databaseIdProvider = (DatabaseIdProvider) resolveClass(type).getDeclaredConstructor().newInstance();
      //配置DatabaseidProvider ,完成初始化
      databaseIdProvider.setProperties(properties);
    }
    Environment environment = configuration.getEnvironment();
    if (environment != null && databaseIdProvider != null) {
      //通过前面确定的DataSource 获取database Id , 并记录到configuration.databaseid 字段中
      String databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource());
      configuration.setDatabaseId(databaseId);
    }
  }

解析typeHandlers

private void typeHandlerElement(XNode parent) {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        if ("package".equals(child.getName())) {
          String typeHandlerPackage = child.getStringAttribute("name");
          typeHandlerRegistry.register(typeHandlerPackage);
        } else {
          String javaTypeName = child.getStringAttribute("javaType");
          String jdbcTypeName = child.getStringAttribute("jdbcType");
          String handlerTypeName = child.getStringAttribute("handler");
          Class<?> javaTypeClass = resolveClass(javaTypeName);
          JdbcType jdbcType = resolveJdbcType(jdbcTypeName);
          Class<?> typeHandlerClass = resolveClass(handlerTypeName);
          if (javaTypeClass != null) {
            if (jdbcType == null) {
              typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);
            } else {
              typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
            }
          } else {
            typeHandlerRegistry.register(typeHandlerClass);
          }
        }
      }
    }
  }

解析mappers

private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
      //处理< mappers >的子节点
      for (XNode child : parent.getChildren()) {
        //<package >子节点
        if ("package".equals(child.getName())) {
          String mapperPackage = child.getStringAttribute("name");
          //扫描指定的包,并向MapperRegistry 注册Mapper 接口
          configuration.addMappers(mapperPackage);
        } else {
          //获取<mapper >节点的resource 、url 、class 属性,这三个属性互斥
          String resource = child.getStringAttribute("resource");
          String url = child.getStringAttribute("url");
          String mapperClass = child.getStringAttribute("class");
          //如果<mapper >节点指定了resource 或是url 属性,则创建XMLMapperBuilder 对象,并通过该对象解析resource 或是url 属性指定的Mapper 配置文件
          if (resource != null && url == null && mapperClass == null) {
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //创建XMLMapperBu 工lder 对象,解析映射配置文件
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url != null && mapperClass == null) {
            ErrorContext.instance().resource(url);
            InputStream inputStream = Resources.getUrlAsStream(url);
            //创建XMLMapperBuilder 对象, 解析映射配置文件
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url == null && mapperClass != null) {
            //如果<mapper >节点指定了class属性,则向MapperRegistry 注册该Mapper 接口
            Class<?> mapperInterface = Resources.classForName(mapperClass);
            configuration.addMapper(mapperInterface);
          } else {
            throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
          }
        }
      }
    }
  }
扫描包 todo
解析resource|url
 public void parse() {
    //判断是否已经加载过该映射文件
    if (!configuration.isResourceLoaded(resource)) {
      configurationElement(parser.evalNode("/mapper"));
      configuration.addLoadedResource(resource);
      //注册Mapper 接口
      bindMapperForNamespace();
    }
//处理configurationElement ()方法中解析失败的< resultMap > 节点
    parsePendingResultMaps();
    //处理configurationElement ()方法中解析失败的< cache-ref >节点
    parsePendingCacheRefs();
    //处理configurationElement ()方法中解析失败的SQL 语句节点
    parsePendingStatements();
  }
解析mapper
private void configurationElement(XNode context) {
    try {
      //获取<mapper > 节点的namespace 属性
      String namespace = context.getStringAttribute("namespace");
      if (namespace == null || namespace.isEmpty()) {
        throw new BuilderException("Mapper's namespace cannot be empty");
      }
      //设置MapperBuilderAssistant的currentNamespace 字段,记录当前命名空间
      builderAssistant.setCurrentNamespace(namespace);
      //解析< cache - ref > 节点
      //多个namespace 共用同一个二级缓存,即同一个Cache 对象,
      cacheRefElement(context.evalNode("cache-ref"));
      //解析< cache >节点,开启二级缓存
      cacheElement(context.evalNode("cache"));
      //解析< parameterMap >节点(该节点已废弃,不再推荐使用)
      parameterMapElement(context.evalNodes("/mapper/parameterMap"));
      //解析< resultMap >节点
      resultMapElements(context.evalNodes("/mapper/resultMap"));
      //解析< sql >节点
      sqlElement(context.evalNodes("/mapper/sql"));
      //解析< select >、< insert >、< update >、< delete >SQL 节点
      buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);
    }
  }
解析crud|cache|cache-ref

针对cache和cache-ref详情请看缓存
crud请看下方crud

解析resultMap
 private ResultMap resultMapElement(XNode resultMapNode) {
    return resultMapElement(resultMapNode, Collections.emptyList(), null);
  }

  private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings, Class<?> enclosingType) {
    ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
//获取< resultMap >节点的type 属性,表示结果集集将被映射成type 指定类型的对象,
    String type = resultMapNode.getStringAttribute("type",
        resultMapNode.getStringAttribute("ofType",
            resultMapNode.getStringAttribute("resultType",
                resultMapNode.getStringAttribute("javaType"))));
//解析type 类型
    Class<?> typeClass = resolveClass(type);
    if (typeClass == null) {
      typeClass = inheritEnclosingType(resultMapNode, enclosingType);
    }
    Discriminator discriminator = null;
    //该集合用于记录解析的结果
    List<ResultMapping> resultMappings = new ArrayList<>(additionalResultMappings);
    //处理< resultMap > 的子节点
    List<XNode> resultChildren = resultMapNode.getChildren();
    for (XNode resultChild : resultChildren) {
      if ("constructor".equals(resultChild.getName())) {
        //处理<constructor> 节点
        processConstructorElement(resultChild, typeClass, resultMappings);
      } else if ("discriminator".equals(resultChild.getName())) {
        //处理<discriminator>节点
        discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
      } else {
        // 处理< id>、<result>、<association>、<collection >等节点
        List<ResultFlag> flags = new ArrayList<>();
        if ("id".equals(resultChild.getName())) {
          //  如果是< id>节点,则向flags 集合中添加ResultFlag.ID
          flags.add(ResultFlag.ID);
        }
        // 创建ResultMapping 对象,并添加到resultMappings 集合中保存
        resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
      }
    }
    //获取< resultMap >的id 属性,默认值会拼笨所有父节点的id 或value 或Property值
    String id = resultMapNode.getStringAttribute("id",
            resultMapNode.getValueBasedIdentifier());
    //获取< resultMap >节点的extends 属性,该属性指定了该< resultMap>节点的继承关系
    String extend = resultMapNode.getStringAttribute("extends");
    //读取< resultMap >节点的autoMapping 属性, 将该属性设置为true ,则启动自动映射功能
      //即自动查找与列名同名的属性名,并调用setter 方法。而设置为false 后, 9)1] 需
//要在< resultMap > 节点内明确注明映射关系才会调用对应的setter 方法。
    Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
    ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);
    try {
      //创建ResultMap 对象,并添加到Configuration.resultMaps 集合中,该集合是StrictMap 类型
      return resultMapResolver.resolve();
    } catch (IncompleteElementException e) {
      configuration.addIncompleteResultMap(resultMapResolver);
      throw e;
    }
  }

 private void processConstructorElement(XNode resultChild, Class<?> resultType, List<ResultMapping> resultMappings) {
   // 获取< constructor >节点的子节点
    List<XNode> argChildren = resultChild.getChildren();
    for (XNode argChild : argChildren) {
      List<ResultFlag> flags = new ArrayList<>();
      //添加CONSTRUCTOR 标志
      flags.add(ResultFlag.CONSTRUCTOR);
      if ("idArg".equals(argChild.getName())) {
        //对于<idArg>节点,添加ID标志
        flags.add(ResultFlag.ID);
      }
      //创建ResultMapping 对象,并添加到resultMappings 集合中
      resultMappings.add(buildResultMappingFromContext(argChild, resultType, flags));
    }
  }

 private Discriminator processDiscriminatorElement(XNode context, Class<?> resultType, List<ResultMapping> resultMappings) {
    String column = context.getStringAttribute("column");
    String javaType = context.getStringAttribute("javaType");
    String jdbcType = context.getStringAttribute("jdbcType");
    String typeHandler = context.getStringAttribute("typeHandler");
    Class<?> javaTypeClass = resolveClass(javaType);
    Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler);
    JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
    //处理<discriminator >节点的子节点
    Map<String, String> discriminatorMap = new HashMap<>();
    for (XNode caseChild : context.getChildren()) {
      String value = caseChild.getStringAttribute("value");
      //调用processNestedResultMappings ( ) 方法创建嵌套的ResultMap 对象
      String resultMap = caseChild.getStringAttribute("resultMap", processNestedResultMappings(caseChild, resultMappings, resultType));
     //记录该列值与对应选择的ResultMap 的Id
      discriminatorMap.put(value, resultMap);
    }
    //创建Discriminator 对象
    return builderAssistant.buildDiscriminator(resultType, column, javaTypeClass, jdbcTypeEnum, typeHandlerClass, discriminatorMap);
  }

 private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, List<ResultFlag> flags) {
    String property;
    if (flags.contains(ResultFlag.CONSTRUCTOR)) {
      property = context.getStringAttribute("name");
    } else {
      property = context.getStringAttribute("property");
    }
    String column = context.getStringAttribute("column");
    String javaType = context.getStringAttribute("javaType");
    String jdbcType = context.getStringAttribute("jdbcType");
    String nestedSelect = context.getStringAttribute("select");


    //如果未指定< association >节点的resultMap属性,则是匿名的嵌套映射,需要通过
    //processNestedResultMappings()方法解析该匿名的嵌套映射
    String nestedResultMap = context.getStringAttribute("resultMap", () ->
        processNestedResultMappings(context, Collections.emptyList(), resultType));


    String notNullColumn = context.getStringAttribute("notNullColumn");
    String columnPrefix = context.getStringAttribute("columnPrefix");
    String typeHandler = context.getStringAttribute("typeHandler");
    String resultSet = context.getStringAttribute("resultSet");
    String foreignColumn = context.getStringAttribute("foreignColumn");
    boolean lazy = "lazy".equals(context.getStringAttribute("fetchType", configuration.isLazyLoadingEnabled() ? "lazy" : "eager"));
    //解析javaType 、typeHandler 和jdbcType
    Class<?> javaTypeClass = resolveClass(javaType);
    Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler);
    JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
    //创建ResultMapping 对象
    return builderAssistant.buildResultMapping(resultType, property, column, javaTypeClass, jdbcTypeEnum, nestedSelect, nestedResultMap, notNullColumn, columnPrefix, typeHandlerClass, flags, resultSet, foreignColumn, lazy);
  }


  public ResultMapping buildResultMapping(
      Class<?> resultType,
      String property,
      String column,
      Class<?> javaType,
      JdbcType jdbcType,
      String nestedSelect,
      String nestedResultMap,
      String notNullColumn,
      String columnPrefix,
      Class<? extends TypeHandler<?>> typeHandler,
      List<ResultFlag> flags,
      String resultSet,
      String foreignColumn,
      boolean lazy) {
    //解析< resultType >节点指定的property 属性的类型
    Class<?> javaTypeClass = resolveResultJavaType(resultType, property, javaType);
    //获取typeHandler 指定的TypeHandler 对象,底层依赖于typeHandlerRegistry ,
    TypeHandler<?> typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);
    //解析column 属性值,当column 是” { propl=coll , prop2=col2 }” 形式时, 会解析成ResultMapping 对象集合,
    // column 的这种形式主要用于嵌套查询的参数传递,
    List<ResultMapping> composites;
    if ((nestedSelect == null || nestedSelect.isEmpty()) && (foreignColumn == null || foreignColumn.isEmpty())) {
      composites = Collections.emptyList();
    } else {
      composites = parseCompositeColumnName(column);
    }
    return new ResultMapping.Builder(configuration, property, column, javaTypeClass)
        .jdbcType(jdbcType)
        .nestedQueryId(applyCurrentNamespace(nestedSelect, true))
        .nestedResultMapId(applyCurrentNamespace(nestedResultMap, true))
        .resultSet(resultSet)
        .typeHandler(typeHandlerInstance)
        .flags(flags == null ? new ArrayList<>() : flags)
        .composites(composites)
        .notNullColumns(parseMultipleColumnNames(notNullColumn))
        .columnPrefix(columnPrefix)
        .foreignColumn(foreignColumn)
        .lazy(lazy)
        .build();
  }
解析sql

  private void sqlElement(List<XNode> list) {
    if (configuration.getDatabaseId() != null) {
      sqlElement(list, configuration.getDatabaseId());
    }
    sqlElement(list, null);
  }
  private void sqlElement(List<XNode> list, String requiredDatabaseId) {
    //遥历< sql >节点
    for (XNode context : list) {
      //获取databaseid 属性
      String databaseId = context.getStringAttribute("databaseId");
      //获取id 属性
      String id = context.getStringAttribute("id");
      //为id 添加命名空间
      id = builderAssistant.applyCurrentNamespace(id, false);
      //检测< sql >的database Id 与当前Configuration 中记录的database Id 是否一致
      if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {
        //记录到XMLMapperBuilder.sqlFragments ( Map<String , XNode >类型)中保存,
        // 在XMLMapperBuilder的构造函数中,可以看到该字段指向了Configuration.sqlFragments 集合
        sqlFragments.put(id, context);
      }
    }
  }

注册mapper

  /**
   * 映射配置文件与对应Mapper 接口的绑定
   */
  private void bindMapperForNamespace() {
   //获取映射配置文件的命名空间
    String namespace = builderAssistant.getCurrentNamespace();
    if (namespace != null) {
      Class<?> boundType = null;
      try {
        //解析命名空间对应的类型
        boundType = Resources.classForName(namespace);
      } catch (ClassNotFoundException e) {
        // ignore, bound type is not required
      }
      // 是否已经加载了boundType 接口
      if (boundType != null && !configuration.hasMapper(boundType)) {
        // Spring may not know the real resource name so we set a flag
        // to prevent loading again this resource from the mapper interface
        // look at MapperAnnotationBuilder#loadXmlResource
       // 追加namespace前缀,并添加到Configuration.loadedResources 集合中保存
        configuration.addLoadedResource("namespace:" + namespace);
       //调用M apperRegistry .addM apper ()方法,注册boundType 接口
        configuration.addMapper(boundType);
      }
    }
  }
 public <T> void addMapper(Class<T> type) {
    mapperRegistry.addMapper(type);
  }
public <T> void addMapper(Class<T> type) {
   //检测type 是否为接口
    if (type.isInterface()) {
     //检测是否已经加载过该接口
      if (hasMapper(type)) {
        throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
      }
      boolean loadCompleted = false;
      try {
       //将Mapper 接口对应的Class 对象和MapperProxyFactory 对象添加到knownMappers 集合
        knownMappers.put(type, new MapperProxyFactory<>(type));
        // It's important that the type is added before the parser is run
        // otherwise the binding may automatically be attempted by the
        // mapper parser. If the type is already known, it won't try.
        //XML 解析和注解的处理
        MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
        parser.parse();
        loadCompleted = true;
      } finally {
        if (!loadCompleted) {
          knownMappers.remove(type);
        }
      }
    }
  }

 /**
   * 解析Mapper 接口中的注解信息
   */
  public void parse() {
    String resource = type.toString();
    //检测是否已经加载过该接口
    if (!configuration.isResourceLoaded(resource)) {
      //检测是否加载过对应的映射配置文件,如果未加载,则创建XMLMapperBuilder 对象解析对应的 映射文件
      loadXmlResource();
      configuration.addLoadedResource(resource);
      assistant.setCurrentNamespace(type.getName());
      //解析@CacheNamespace i主解
      parseCache();
      //解析@CacheNamespaceRef 注解
      parseCacheRef();
      //遍历接口中定义的全部方法
      for (Method method : type.getMethods()) {
        if (!canHaveStatement(method)) {
          continue;
        }
        if (getSqlCommandType(method) == SqlCommandType.SELECT && method.getAnnotation(ResultMap.class) == null) {
          parseResultMap(method);
        }
        try {
          parseStatement(method);
        } catch (IncompleteElementException e) {
          //如果解析过程出现IncompleteElementException异常,可能是引用了未解析的注解,
          //这里将出现异常的方法添加到Configuration.incompleteMethods 集合中暂存,
          //该集合是LinkedList< MethodResolver >类型
          configuration.addIncompleteMethod(new MethodResolver(this, method));
        }
      }
    }
    //遍历Configuration.incompleteMethods 集合中记录的为解析的方法,并重新进行解析
    parsePendingMethods();
  }

buildSqlSessionFactory

  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

  public DefaultSqlSessionFactory(Configuration configuration) {
    this.configuration = configuration;
  }

openSession

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

 /**
   * 通过数据源获取数据库连接, 并创建Executor 对象以及DefaultSqlSession 对象
   * @param execType
   * @param level
   * @param autoCommit
   * @return
   */
  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      //获取mybatis-config.xml 配置文件中配置的Environment 对象
      final Environment environment = configuration.getEnvironment();
      //获取的TransactionFactory 对象
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
     //创建Transaction 对象
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      //根据配置创建Executor 对象
     final Executor executor = configuration.newExecutor(tx, execType);
     //创建DefaultSqlSession 对象
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      // 关闭Transaction
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

根据配置创建Executor 对象

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor 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);
    }
   //根据配置决定是否开启二级缓存的功能
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
   //创建Executor的代理对象
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }

插件支持

  public Object pluginAll(Object target) {
  //遍历interceptors 集合
    for (Interceptor interceptor : interceptors) {
     //调用
      target = interceptor.plugin(target);
    }
    return target;
  }
//决定是否触发intercept ()方法
  default Object plugin(Object target) {
    return Plugin.wrap(target, this);
  }
 public static Object wrap(Object target, Interceptor interceptor) {
  //负责处理@Signature注解
    Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
  //获取目标类型
    Class<?> type = target.getClass();
  //获取目标类型实现的接口
    Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
    if (interfaces.length > 0) {
    //使用JDK 动态代理的方式创建代理对象
      return Proxy.newProxyInstance(
          type.getClassLoader(),
          interfaces,
          new Plugin(target, interceptor, signatureMap));
    }
    return target;
  }

getMapper

  @Override
  public <T> T getMapper(Class<T> type) {
    return configuration.getMapper(type, this);
  }
  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
  }
  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    //查找指定type 对应的MapperProxyFactory 对象
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null) {
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    }
    try {
      //创建实现了type 接口的代理对象
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }
  public T  newInstance(SqlSession sqlSession) {
    //创建MapperProxy 对象,每次调用都会创建新的MapperProxy 对象
    final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }

  @SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy<T> mapperProxy) {
    //创建实现了mapperinterface 接口的代理对象
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

调用mapper

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      //如果目标方法继承自Object ,则直接调用目标方法
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
      } else {
        //从缓存中获取MapperMethod 对象,如缓存中没有,则创建新的MapperMethod 对象并添加到缓存中
        return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
  }

  private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {
    try {
      return methodCache.computeIfAbsent(method, m -> {
        //如果是默认方法
        if (m.isDefault()) {
          try {
            if (privateLookupInMethod == null) {
              return new DefaultMethodInvoker(getMethodHandleJava8(method));
            } else {
              return new DefaultMethodInvoker(getMethodHandleJava9(method));
            }
          } catch (IllegalAccessException | InstantiationException | InvocationTargetException
              | NoSuchMethodException e) {
            throw new RuntimeException(e);
          }
        } else {
          //创建MapperMethodInvoker
          return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
        }
      });
    } catch (RuntimeException re) {
      Throwable cause = re.getCause();
      throw cause == null ? re : cause;
    }
  }

  public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
    // 记录了SQL 语句的名称和类型
    this.command = new SqlCommand(config, mapperInterface, method);
    // Mapper 接口中对应方法的相关信息
    this.method = new MethodSignature(config, mapperInterface, method);
  }
 public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
      final String methodName = method.getName();
      final Class<?> declaringClass = method.getDeclaringClass();
      MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass,
          configuration);
      if (ms == null) {
        //处理@ Flush i主解
        if (method.getAnnotation(Flush.class) != null) {
          name = null;
          type = SqlCommandType.FLUSH;
        } else {
          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);
        }
      }
    }
  private MappedStatement resolveMappedStatement(Class<?> mapperInterface, String methodName,
        Class<?> declaringClass, Configuration configuration) {
      // SQL 语句的名称是由Mapper 接口的名称与对应的方法名称组成的
      String statementId = mapperInterface.getName() + "." + methodName;
      //检测是否有该名称的SQL 语句
      if (configuration.hasStatement(statementId)) {
        //从Configuration.mappedStatements集合中查找对应的MappedStatement对象
        return configuration.getMappedStatement(statementId);
      } else if (mapperInterface.equals(declaringClass)) {
        return null;
      }
      //如果指定方法是在父接口中定义的, 则在此进行继承结构的处理
      for (Class<?> superInterface : mapperInterface.getInterfaces()) {
        if (declaringClass.isAssignableFrom(superInterface)) {
          MappedStatement ms = resolveMappedStatement(superInterface, methodName,
              declaringClass, configuration);
          if (ms != null) {
            return ms;
          }
        }
      }
      return null;
    }
  }

    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();
      }
      //初始化returnsVoid 、returnsMany 、returnsCursor 、map Key 、returnsMap 等字段
      this.returnsVoid = void.class.equals(this.returnType);
      this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
      this.returnsCursor = Cursor.class.equals(this.returnType);
      this.returnsOptional = Optional.class.equals(this.returnType);
      //若MethodSignature 对应方法的返回位是Map 且指定了@ Map Key注解,则使用getMapKey ()方法处理
      this.mapKey = getMapKey(method);
      this.returnsMap = this.mapKey != null;
      //初始化rowBoundsindex 和resultHandlerindex 字段
      this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
      this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
      //创建ParamNameResolver 对象
      this.paramNameResolver = new ParamNameResolver(configuration, method);
    }
 //查找指定类型的参数在参数列表中的位置
    private Integer getUniqueParamIndex(Method method, Class<?> paramType) {
      Integer index = null;
      final Class<?>[] argTypes = method.getParameterTypes();
      for (int i = 0; i < argTypes.length; i++) {

        if (paramType.isAssignableFrom(argTypes[i])) {
          //记录paramType 类型参数在参数列表中的位置索引
          if (index == null) {
            index = i;
          } else {
            // RowBounds 和ResultHandler 类型的参数只能有一个,不能重复出现
            throw new BindingException(method.getName() + " cannot have multiple " + paramType.getSimpleName() + " parameters");
          }
        }
      }
      return index;
    }
    public boolean returnsOptional() {
      return returnsOptional;
    }

    //查找指定类型的参数在参数列表中的位置
    private Integer getUniqueParamIndex(Method method, Class<?> paramType) {
      Integer index = null;
      final Class<?>[] argTypes = method.getParameterTypes();
      for (int i = 0; i < argTypes.length; i++) {

        if (paramType.isAssignableFrom(argTypes[i])) {
          //记录paramType 类型参数在参数列表中的位置索引
          if (index == null) {
            index = i;
          } else {
            // RowBounds 和ResultHandler 类型的参数只能有一个,不能重复出现
            throw new BindingException(method.getName() + " cannot have multiple " + paramType.getSimpleName() + " parameters");
          }
        }
      }
      return index;
    }
 public ParamNameResolver(Configuration config, Method method) {
    this.useActualParamName = config.isUseActualParamName();
   //获取参数列表中每个参数的类型
    final Class<?>[] paramTypes = method.getParameterTypes();
   //获取参数列表上的注解
    final Annotation[][] paramAnnotations = method.getParameterAnnotations();
   //该集合用于记录参数索引与参数名称的对应关系
    final SortedMap<Integer, String> map = new TreeMap<>();
    int paramCount = paramAnnotations.length;
    // get names from @Param annotations
    for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
     //如参数是RowBounds 类型或ResultHandler 类型,跳过对该参数的分析
      if (isSpecialParameter(paramTypes[paramIndex])) {
        // skip special parameters
        continue;
      }
      String name = null;
     // 遥历该参数对应的i主解集合
      for (Annotation annotation : paramAnnotations[paramIndex]) {
       // @Param出现过一次,就将hasParamAnnotation 初始化为true
        if (annotation instanceof Param) {
          hasParamAnnotation = true;
         //获取自Param注解指定的参数名称
          name = ((Param) annotation).value();
          break;
        }
      }
      if (name == null) {
        // @Param was not specified.
       //该参数没有对应的@Param注解,则根据配置决定是否使用参数实际名称作为其名称
        if (useActualParamName) {
          name = getActualParamName(method, paramIndex);
        }
        if (name == null) {
          // use the parameter index as the name ("0", "1", ...)
          // gcode issue #71
         //使用参数的索引作为其名称
          name = String.valueOf(map.size());
        }
      }
     // 记录到map 中保存
      map.put(paramIndex, name);
    }
   // 初始化names 集合
    names = Collections.unmodifiableSortedMap(map);
  }

执行调用

    @Override
    public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
      return mapperMethod.execute(sqlSession, args);
    }
//根据SQL 语句的类型调用SqI Session 对应的方法完成数据库操作。
  public Object execute(SqlSession sqlSession, Object[] args) {
    Object result;
    //根据SQL 语句的类型调用SqlSession 对应的方法
    switch (command.getType()) {
      case INSERT: {
        //使用ParamNameResolver处理args []数组(用户传入的实参列表),将用户传入的实参与指定参数名称关联起来
        Object param = method.convertArgsToSqlCommandParam(args);
        //调用SqlSession.insert ()方法, rowCountResult ()方法会根据method 字段中记录的方法的 返回值类型对结果进行转换
        result = rowCountResult(sqlSession.insert(command.getName(), param));
        break;
      }
      case UPDATE: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.update(command.getName(), param));
        break;
      }
      case DELETE: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.delete(command.getName(), param));
        break;
      }
      case SELECT:
        //处理返回值为void 且ResultSet 通过ResultHandler 处理的方法
        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()) {
          // 处理返回值为Curs or 的方法
          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;
  }

C

R

//负责将args []数纽( 用户传入的实参列表)转换成SQL 语句对应的参数列表,
    public Object convertArgsToSqlCommandParam(Object[] args) {
      return paramNameResolver.getNamedParams(args);
    }
 public Object getNamedParams(Object[] args) {
    final int paramCount = names.size();
    // 无参数,返回null
    if (args == null || paramCount == 0) {
      return null;
    } else if (!hasParamAnnotation && paramCount == 1) {
      // 未使用@Param且只有一个参数
      Object value = args[names.firstKey()];
      return wrapToMapIfCollection(value, useActualParamName ? names.get(0) : null);
    } else {
      //处理使用@Paramd主解指定了参数名称或有多个参数的情况
      // param这个Map中记录了参数名称与实参之间的对应关系。ParamMap继承了HashMap ,如果向
      // ParamMap 中添加已经存在的key ,会报错,其他行为与HashMap 相同
      final Map<String, Object> param = new ParamMap<>();
      int i = 0;
      for (Map.Entry<Integer, String> entry : names.entrySet()) {
        //将参数名与实参对应关系记录到pa ram 中
        param.put(entry.getValue(), args[entry.getKey()]);
        // add generic param names (param1, param2, ...)
        // 下面是为参数创建” param+索引”格式的默认参数名称,例如: paraml , param2等,并添加到param 集合中
        final String genericParamName = GENERIC_NAME_PREFIX + (i + 1);
        // ensure not to overwrite parameter named with @Param
        //如@Param主解指定的参数名称就是” param+索引”格式的,则不需要再添加
        if (!names.containsValue(genericParamName)) {
          param.put(genericParamName, args[entry.getKey()]);
        }
        i++;
      }
      return param;
    }
  }
  @Override
  public <T> T selectOne(String statement, Object parameter) {
    // Popular vote was to return null on 0 results and throw exception on too many.
    List<T> list = this.selectList(statement, parameter);
    if (list.size() == 1) {
      return list.get(0);
    } else if (list.size() > 1) {
      throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
    } else {
      return null;
    }
  }
  @Override
  public <E> List<E> selectList(String statement, Object parameter) {
    return this.selectList(statement, parameter, RowBounds.DEFAULT);
  }
  @Override
  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      MappedStatement ms = configuration.getMappedStatement(statement);
      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();
    }
  }
    @Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    //获取BoundSql 对象
    BoundSql boundSql = ms.getBoundSql(parameter);
   // 创建CacheKey 对象
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
   // 调用query ()的另一个重载,继续后续处理
    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
  }

 public BoundSql getBoundSql(Object parameterObject) {
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings == null || parameterMappings.isEmpty()) {
      boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
    }

    // check for nested result maps in parameter mappings (issue #30)
    for (ParameterMapping pm : boundSql.getParameterMappings()) {
      String rmId = pm.getResultMapId();
      if (rmId != null) {
        ResultMap rm = configuration.getResultMap(rmId);
        if (rm != null) {
          hasNestedResultMaps |= rm.hasNestedResultMaps();
        }
      }
    }

    return boundSql;
  }
 @Override
  public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
    //检测当前Executor 是否已经关闭
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    //创建CacheKey 对象
    CacheKey cacheKey = new CacheKey();
    //将MappedStatement 的id 添加到Cache Key 对象中
    cacheKey.update(ms.getId());
    //将off set 添加到CacheKey 对象中
    cacheKey.update(rowBounds.getOffset());
   //将limit 添加到CacheKey 对象中
    cacheKey.update(rowBounds.getLimit());
    //将SQL 语句添加到CacheKey 对象中
    cacheKey.update(boundSql.getSql());
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
    // mimic DefaultParameterHandler logic
    //获取用户传入的实参,并添加.f1J CacheKey 对象中
    for (ParameterMapping parameterMapping : parameterMappings) {
      //过滤输出类型的参数
      if (parameterMapping.getMode() != ParameterMode.OUT) {
        Object value;
        String propertyName = parameterMapping.getProperty();
        if (boundSql.hasAdditionalParameter(propertyName)) {
          value = boundSql.getAdditionalParameter(propertyName);
        } else if (parameterObject == null) {
          value = null;
        } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
          value = parameterObject;
        } else {
          MetaObject metaObject = configuration.newMetaObject(parameterObject);
          value = metaObject.getValue(propertyName);
        }
        //将实参添加到CacheKey 对象中
        cacheKey.update(value);
      }
    }
    //如果Environment 的id 不为空,则将其添加到CacheKey 中
    if (configuration.getEnvironment() != null) {
      // issue #176
      cacheKey.update(configuration.getEnvironment().getId());
    }
    return cacheKey;
  }
  public void update(Object object) {
    int baseHashCode = object == null ? 1 : ArrayUtil.hashCode(object);

    count++;
    checksum += baseHashCode;
    baseHashCode *= count;

    hashcode = multiplier * hashcode + baseHashCode;

    //将object 添加到updateList 集合中
    updateList.add(object);
  }
@Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
  //检测当前Executor 是否已经关闭
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      //非嵌套查询,并且< select >节点配置的flushCache 属性为true 时,才会清空一级缓存
     // flushCache 配置项是影响一级缓存中结果对象存活时长的第一个方面
      clearLocalCache();
    }
    List<E> list;
    try {
      //培加查询层数
      queryStack++;
      //查询一级缓存
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
      if (list != null) {
        //针对存储过程调用的处理, 其功能是: 在一级缓存命中时,获取缓存中保存的输出类型参数,并设置到用户传入的实参( parameter )对象中
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {
        //其中会调用doQuery ()方法完成数据库查询,并得到映射后的结果对象
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
      //当前查询完成,查询层数减少
      queryStack--;
    }
    if (queryStack == 0) {
      //延迟加载
     // 在最外层的查询结束时,所有嵌套查询也已经完成,相关缓存项也已经完全加载,所以在这里可以
      //触发DeferredLoad 加载一级缓存中记录的嵌套查询的结果对象
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      }
      // issue #601
    //加裁完成后, 清空deferredLoads 集合
      deferredLoads.clear();
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
        // issue #482
       //根据localCacheScope 配置决定是否清空一级缓存,localCacheScope 配置是影响一级缓
       //存中结果对象存活时长的第二个方面
        clearLocalCache();
      }
    }
    return list;
  }
  private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    List<E> list;
    // 在缓存中添加占位符
    localCache.putObject(key, EXECUTION_PLACEHOLDER);
    try {
      //调用doQuery ()方法(抽象方法),完成数据库查询操作,并返回结果对象
      list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
    } finally {
      //删除占位符
      localCache.removeObject(key);
    }
    //将真正的结果对象添加到一级缓存中
    localCache.putObject(key, list);
    //是否为存储过程调用
    if (ms.getStatementType() == StatementType.CALLABLE) {
     //缓存输出类型的参数
      localOutputParameterCache.putObject(key, parameter);
    }
    return list;
  }
  @Override
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      //获取配置对象
      Configuration configuration = ms.getConfiguration();
      // 创建StatementHandler 对象,实际返回的是RoutingStatementHandler 对象,
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
     //完成Statement 的创建和初始化,该方法首先会调用StatementHandler.prepare ()方法创建
     //Statement 对象, 然后调用StatementH andler. parameterize ()方法处理占位符
      stmt = prepareStatement(handler, ms.getStatementLog());
      //调用StatementHandler.query ()方法,执行SQL 语句,并通过ResultSetHandler 完成结果集的映射
      return handler.query(stmt, resultHandler);
    } finally {
      //关闭Statement对象
      closeStatement(stmt);
    }
  }
  public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    //利用策略模式创建不同的StatementHandler
    StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
    //拦截器代理
    statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    return statementHandler;
  }
  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    Connection connection = getConnection(statementLog);
    //创建Statement 对象
    stmt = handler.prepare(connection, transaction.getTimeout());
   //处理占位符
    handler.parameterize(stmt);
    return stmt;
  }

创建Statement 对象
  @Override
  public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
    return delegate.prepare(connection, transactionTimeout);
  }
  @Override
  public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
    ErrorContext.instance().sql(boundSql.getSql());
    Statement statement = null;
    try {
      //实例化statement
      statement = instantiateStatement(connection);
      setStatementTimeout(statement, transactionTimeout);
      setFetchSize(statement);
      return statement;
    } catch (SQLException e) {
      closeStatement(statement);
      throw e;
    } catch (Exception e) {
      closeStatement(statement);
      throw new ExecutorException("Error preparing statement.  Cause: " + e, e);
    }
  }

  @Override
  protected Statement instantiateStatement(Connection connection) throws SQLException {
    //获取待执行的SQL 语句
    String sql = boundSql.getSql();
   // 根据MappedStatement.keyGenerator 字段的值,创建PreparedStatement 对象
    if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
      String[] keyColumnNames = mappedStatement.getKeyColumns();
      if (keyColumnNames == null) {
       // 返回数据库生成的主键
        return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
      } else {
       // 在insert 语句执行完成之后,会将key ColumnNames 指定的列返回
        return connection.prepareStatement(sql, keyColumnNames);
      }
    } else if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {
      // 创建普通的PreparedSta tement 对象
      return connection.prepareStatement(sql);
    } else {
     // 设置结果集是否可以滚动以及其游标是否可以上下移动,设置结果集是否可更新
      return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
    }
  }
处理占位符
  @Override
  public void parameterize(Statement statement) throws SQLException {
    delegate.parameterize(statement);
  }
  @Override
  public void parameterize(Statement statement) throws SQLException {
    parameterHandler.setParameters((PreparedStatement) statement);
  }

  @Override
  public void setParameters(PreparedStatement ps) {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
    // 取出sql 中的参数映射列表
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    // 检测parameterMappings 集合是否为空
    if (parameterMappings != null) {
      for (int i = 0; i < parameterMappings.size(); i++) {
        ParameterMapping parameterMapping = parameterMappings.get(i);
        //过滤掉存储过程中的输出参数
        if (parameterMapping.getMode() != ParameterMode.OUT) {
          //记录绑定的实参
          Object value;
          //获取参数名称
          String propertyName = parameterMapping.getProperty();
          //获取对应的实参位
          if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
            value = boundSql.getAdditionalParameter(propertyName);
          } else if (parameterObject == null) {
            //整个实参为空
            value = null;
          } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
            // 实参可以直接通过TypeHandler 转换成JdbcType
            value = parameterObject;
          } else {
            //获取对象中相应的属性值或查找Map对象中值
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
          //获取ParameterMapping 中设置的TypeHandler 对象
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) {
            jdbcType = configuration.getJdbcTypeForNull();
          }
          try {
            //通过TypeHandler . setParametera ()方法会调用PreparedStatement.set *()方法 为SQL 语句绑定相应的实参,
            typeHandler.setParameter(ps, i + 1, value, jdbcType);
          } catch (TypeException | SQLException e) {
            throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
          }
        }
      }
    }
  }
  public boolean hasTypeHandler(Class<?> javaType) {
    return hasTypeHandler(javaType, null);
  }
    public boolean hasTypeHandler(Class<?> javaType, JdbcType jdbcType) {
    return javaType != null && getTypeHandler((Type) javaType, jdbcType) != null;
  }
 /**
   * 根据指定的Java类型和JdbcType 类型查找相应的TypeHandler对象,
   * @param type
   * @return
   */
  private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {
    if (ParamMap.class.equals(type)) {
      return null;
    }
    //查找(或初始化) Java 类型对应的TypeHandler集合
    Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = getJdbcHandlerMap(type);
    TypeHandler<?> handler = null;
    if (jdbcHandlerMap != null) {
      // 根据JdbcType 类型查找TypeHandler 对象
      handler = jdbcHandlerMap.get(jdbcType);
      if (handler == null) {
        handler = jdbcHandlerMap.get(null);
      }
      if (handler == null) {
        // #591
        //如果jdbcHandlerMap 只注册了一个Type Handler ,则使用此TypeHandler 对象
        handler = pickSoleHandler(jdbcHandlerMap);
      }
    }
    // type drives generics here
    return (TypeHandler<T>) handler;
  }
  private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMap(Type type) {
    //查找指定Java 类型对应的TypeHandler 集合
    Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(type);
    //检测是否为空集合标识
    if (NULL_TYPE_HANDLER_MAP.equals(jdbcHandlerMap)) {
      return null;
    }
    //初始化指定Java 类型的T ypeHandler 集合
    if (jdbcHandlerMap == null && type instanceof Class) {
      Class<?> clazz = (Class<?>) type;
      //枚举类型的处理
      if (Enum.class.isAssignableFrom(clazz)) {
        Class<?> enumClass = clazz.isAnonymousClass() ? clazz.getSuperclass() : clazz;
        jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(enumClass, enumClass);
        if (jdbcHandlerMap == null) {
          register(enumClass, getInstance(enumClass, defaultEnumTypeHandler));
          return typeHandlerMap.get(enumClass);
        }
      } else {
        //查找父类对应的TypeHandler 集合,并作为初始集合
        jdbcHandlerMap = getJdbcHandlerMapForSuperclass(clazz);
      }
    }
    typeHandlerMap.put(type, jdbcHandlerMap == null ? NULL_TYPE_HANDLER_MAP : jdbcHandlerMap);
    return jdbcHandlerMap;
  }
 @Override
  public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
    if (parameter == null) {
      if (jdbcType == null) {
        throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
      }
      try {
        ps.setNull(i, jdbcType.TYPE_CODE);
      } catch (SQLException e) {
        throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . "
              + "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. "
              + "Cause: " + e, e);
      }
    } else {
      try {
        setNonNullParameter(ps, i, parameter, jdbcType);
      } catch (Exception e) {
        throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . "
              + "Try setting a different JdbcType for this parameter or a different configuration property. "
              + "Cause: " + e, e);
      }
    }
  }

  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, Integer parameter, JdbcType jdbcType)
      throws SQLException {
    ps.setInt(i, parameter);
  }
查询以及处理结果集
  @Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    ps.execute();
    return resultSetHandler.handleResultSets(ps);
  }

 /**
   * 处理Statement 、PreparedStatement 产生的结果集,还可以处理
   * Callab leStatement 调用存储过程产生的多结果集。
   * @param stmt
   * @return
   * @throws SQLException
   */
  @Override
  public List<Object> handleResultSets(Statement stmt) throws SQLException {
    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());

    //保存映射结果集得到的结果对象
    final List<Object> multipleResults = new ArrayList<>();

    int resultSetCount = 0;
    // 获取第一个ResultSet 对象,可能存在多个ResultSet ,这里只获取第一个ResultSet
    ResultSetWrapper rsw = getFirstResultSet(stmt);

    List<ResultMap> resultMaps = mappedStatement.getResultMaps();
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount);
      //结果集不为空,则resultMaps 集合不能为空,
      //遍历resultMaps 集合
    while (rsw != null && resultMapCount > resultSetCount) {
        //获取该结果集对应的ResultMap 对象
      ResultMap resultMap = resultMaps.get(resultSetCount);
          //根据ResultMap 中定义的映射规则对ResultSet 进行映射, 并将映射的结果对象添加到 multipleResults 集合中保存
      //将未解析的结果集保存nextResultMaps暂存
      handleResultSet(rsw, resultMap, multipleResults, null);
        //获取下一个结果集
      rsw = getNextResultSet(stmt);
        //清空nestedResultObjects 集合
      cleanUpAfterHandlingResultSet();
        // 递增resultSetCount
      resultSetCount++;
    }

    //获取MappedStatement.resultSets属性。该属性仅对多结果集的情况适用,该属性将列出语句执
//行后返回的结果集,并给每个结果集一个名称,名称是逗号分隔的
    String[] resultSets = mappedStatement.getResultSets();
    if (resultSets != null) {
      while (rsw != null && resultSetCount < resultSets.length) {
        //根据resultSet 的名称,获取未处理的ResultMapping
        ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
        if (parentMapping != null) {
         //获取映射该结果集要使用的ResultMap 对象
          String nestedResultMapId = parentMapping.getNestedResultMapId();
          ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
          //根据ResultMap 对象映射结果集
          handleResultSet(rsw, resultMap, null, parentMapping);
        }
       // 获取下一个结果集
        rsw = getNextResultSet(stmt);
        // 清空nestedResultObjects 集合
        cleanUpAfterHandlingResultSet();
       // 递增resultSetCount
        resultSetCount++;
      }
    }

    return collapseSingleResultList(multipleResults);
  }

一级缓存

在这里插入图片描述

  @Override
  public void putObject(Object key, Object value) {
    cache.put(key, value);
  }
对二级缓存的支持
  @Override
  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
      //步骤1 :获取BoundSql 对象,
    BoundSql boundSql = ms.getBoundSql(parameterObject);
      //创建CacheKey 对象
    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

反射

在这里插入图片描述

  public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
    return new MetaClass(type, reflectorFactory);
  }
  private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
    this.reflectorFactory = reflectorFactory;
    this.reflector = reflectorFactory.findForClass(type);
  }
  @Override
  public Reflector findForClass(Class<?> type) {
    //检测是否开启缓存
    if (classCacheEnabled) {
      // synchronized (type) removed see issue #461
      return reflectorMap.computeIfAbsent(type, Reflector::new);
    } else {
      //未开启缓存,则直接创建并返回Reflector对象
      return new Reflector(type);
    }
  }
 public Reflector(Class<?> clazz) {
    type = clazz;
    //查找clazz 的默认构造方法(无参构造方法)
    addDefaultConstructor(clazz);
    //处理clazz 中的getter 方法,填充getMethods 集合和getTypes 集合
    addGetMethods(clazz);
    //处理clazz 中的set ter 方法,填充setMethods 集合和set Types 集合
    addSetMethods(clazz);
    //处理没有g etter I setter 方法的字段
    addFields(clazz);
    //根据getMethodslsetMethods 集合,初始化可读/写属性的名称集合
    readablePropertyNames = getMethods.keySet().toArray(new String[0]);
    writablePropertyNames = setMethods.keySet().toArray(new String[0]);
    //初始化caseinsensitivePropertyMap 集合,其中记录了所有大写格式的属性名称
    for (String propName : readablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
    for (String propName : writablePropertyNames) {
      caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
    }
  }

查找clazz 的默认构造方法(无参构造方法)

  private void addDefaultConstructor(Class<?> clazz) {
    //获取所有声明构造
    Constructor<?>[] constructors = clazz.getDeclaredConstructors();
    Arrays.stream(constructors).
      //过滤默认构造
      filter(constructor -> constructor.getParameterTypes().length == 0)
      //查询所有
      .findAny()
      //设置默认构造
      .ifPresent(constructor -> this.defaultConstructor = constructor);
  }

处理clazz 中的getter 方法

  /**
   * 填充getMethods 集合和getTypes 集合
   * @param clazz
   */
  private void addGetMethods(Class<?> clazz) {
    Map<String, List<Method>> conflictingGetters = new HashMap<>();
    //获取指定类以及其父类和接口中定义的方法
    Method[] methods = getClassMethods(clazz);
    //对get方法过滤
    Arrays.stream(methods).filter(m ->
        //JavaBean 中getter 方法的方法名长度大于3 且必须以” get ” 开头
      m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName()))
      .forEach(m ->
          //记录到conflictingGetters集合中
        addMethodConflict(conflictingGetters,
          //获取对应的属性名称
          PropertyNamer.methodToProperty(m.getName()), m));
    //对方法同名返回值不一样的处理
    resolveGetterConflicts(conflictingGetters);
  }
  
 private Method[] getClassMethods(Class<?> clazz) {
    //用于记录指定类中定义的全部方法的唯一签名以及对应的Meth od 对象
    Map<String, Method> uniqueMethods = new HashMap<>();
    Class<?> currentClass = clazz;
    while (currentClass != null && currentClass != Object.class) {
      //记录currentClass 这个类中定义的全部方法.桥方法除外
      addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());

      // we also need to look for interface methods -
      // because the class may be abstract
      //记录接口中定义的方法
      Class<?>[] interfaces = currentClass.getInterfaces();
      for (Class<?> anInterface : interfaces) {
        addUniqueMethods(uniqueMethods, anInterface.getMethods());
      }
      //获取父类,继续while 循环
      currentClass = currentClass.getSuperclass();
    }

    Collection<Method> methods = uniqueMethods.values();

    return methods.toArray(new Method[0]);
  }

  private void addUniqueMethods(Map<String, Method> uniqueMethods, Method[] methods) {
    for (Method currentMethod : methods) {
      //过滤桥接方法,也就是为了兼容泛型,重新定义了一个方法,调用原来的方法,定位桥
      if (!currentMethod.isBridge()) {
      //方法得到的方法签名是全局唯一的,可以作为该方法 的唯一标识
        String signature = getSignature(currentMethod);
        // check to see if the method is already known
        // if it is known, then an extended class must have
        // overridden a method
        //检测是否在子类中已经添加过该方法,如果在子类中已经添加过,无须再向uniqueMethods 集合中添加该方法了
        if (!uniqueMethods.containsKey(signature)) {
          //记录该签名和方法的对应关系
          uniqueMethods.put(signature, currentMethod);
        }
      }
    }
  }

  private String getSignature(Method method) {
    //格式 org.apache.ibatis.cache.Cache#getCache:java.lang.String
    StringBuilder sb = new StringBuilder();
    Class<?> returnType = method.getReturnType();
    if (returnType != null) {
      sb.append(returnType.getName()).append('#');
    }
    sb.append(method.getName());
    Class<?>[] parameters = method.getParameterTypes();
    for (int i = 0; i < parameters.length; i++) {
      sb.append(i == 0 ? ':' : ',').append(parameters[i].getName());
    }
    return sb.toString();
  }


  //检测方法是否为getter方法
  public static boolean isGetter(String name) {
    return (name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2);
  }

  //将方法名转换成属性名
  public static String methodToProperty(String name) {
    if (name.startsWith("is")) {
      name = name.substring(2);
    } else if (name.startsWith("get") || name.startsWith("set")) {
      name = name.substring(3);
    } else {
      throw new ReflectionException("Error parsing property name '" + name + "'.  Didn't start with 'is', 'get' or 'set'.");
    }

    if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
      name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
    }

    return name;
  }
  private void addMethodConflict(Map<String, List<Method>> conflictingMethods, String name, Method method) {
    //排除序列化id的get
    if (isValidPropertyName(name)) {
        // key:方法名
         //value:方法
      List<Method> list = conflictingMethods.computeIfAbsent(name, k -> new ArrayList<>());
      list.add(method);
    }
  }
 private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
    for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) {
      Method winner = null;
      String propName = entry.getKey();
      boolean isAmbiguous = false;
      for (Method candidate : entry.getValue()) {
        if (winner == null) {
          winner = candidate;
          continue;
        }
        //同一属性名称存在多个getter方法,则需要比较这些getter方法的返回,选择getter方法
        //迭代过程中的临时变量,用于记录迭代到目前为止,最适合作为getter 方法的Method
        Class<?> winnerType = winner.getReturnType();
        Class<?> candidateType = candidate.getReturnType();
        if (candidateType.equals(winnerType)) {
          //对boolean处理
          if (!boolean.class.equals(candidateType)) {
            isAmbiguous = true;
            break;
          } else if (candidate.getName().startsWith("is")) {
            winner = candidate;
          }
        } else if (candidateType.isAssignableFrom(winnerType)) {
          // OK getter type is descendant
          //当前最适合的方法的返回佳是当前方法返回的子类,什么都不做,当前最适合的方法 依然不变
        } else if (winnerType.isAssignableFrom(candidateType)) {
          //当前方法的返回位是当前最适合的方法的返回值的子类,更新临时交量getter,当前的getter 方法成为最适合的getter 方法
          winner = candidate;
        } else {
          //返回值相同,二义性,抛出异常
          isAmbiguous = true;
          break;
        }
      }
      //添加到getMethods 集合并填充get Types 集合
      addGetMethod(propName, winner, isAmbiguous);
    }
  }

  private void addGetMethod(String name, Method method, boolean isAmbiguous) {
    MethodInvoker invoker = isAmbiguous
      ? new AmbiguousMethodInvoker(method, MessageFormat.format(
      "Illegal overloaded getter method with ambiguous type for property ''{0}'' in class ''{1}''. This breaks the JavaBeans specification and can cause unpredictable results.",
      name, method.getDeclaringClass().getName()))
      :
    //将属性名以及对应的Methodinvoker对象添加getMethods集合中,
      new MethodInvoker(method);
    getMethods.put(name, invoker);
    //获取返回值的Type
    Type returnType = TypeParameterResolver.resolveReturnType(method, type);
    //将属性名称及其getter方法的返回位类型添加到getTypes集合中保存
    getTypes.put(name, typeToClass(returnType));
  }

  public static Type resolveReturnType(Method method, Type srcType) {
    //获取方法返回值
    Type returnType = method.getGenericReturnType();
    Class<?> declaringClass = method.getDeclaringClass();
    return resolveType(returnType, srcType, declaringClass);
  }
  private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
    if (type instanceof TypeVariable) {
      return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
    } else if (type instanceof ParameterizedType) {
      return resolveParameterizedType(
        //待解析的ParameterizedType 类型;
        (ParameterizedType) type,
        //解析操作的起始类型testType.SubClassA<Long>
        srcType,
        //定义该字段或方法的类的Class 对象ClassA
        declaringClass);
    } else if (type instanceof GenericArrayType) {
      //根据数组元素类型选择合适的方法进行解析
      return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
    } else {
      return type;//Class 类型
    }
  }

处理clazz 中的setter 方法

  private void addSetMethods(Class<?> clazz) {
    Map<String, List<Method>> conflictingSetters = new HashMap<>();
    Method[] methods = getClassMethods(clazz);
    Arrays.stream(methods).filter(m -> m.getParameterTypes().length == 1 && PropertyNamer.isSetter(m.getName()))
      .forEach(m -> addMethodConflict(conflictingSetters, PropertyNamer.methodToProperty(m.getName()), m));
    resolveSetterConflicts(conflictingSetters);
  }

处理没有getter setter 方法的字段

  /**
   * 添加字段
   * @param clazz
   */
  private void addFields(Class<?> clazz) {
    Field[] fields = clazz.getDeclaredFields();
    for (Field field : fields) {
      //当setMethods 集合不包含同名属性时,将其记录到setMethods 集合和set Types 集合
      if (!setMethods.containsKey(field.getName())) {
        // issue #379 - removed the check for final because JDK 1.5 allows
        // modification of final fields through reflection (JSR-133). (JGB)
        // pr #16 - final static can only be set by the classloader
        int modifiers = field.getModifiers();
        //过滤掉final和static 修饰的字段
        if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {
          addSetField(field);
        }
      }
      //当getMethods 集合中不包含同名属性时,将其记录到getMethods 集合和getTypes 集合
      if (!getMethods.containsKey(field.getName())) {
        addGetField(field);
      }
    }
    if (clazz.getSuperclass() != null) {
      //处理父类中定义的字段
      addFields(clazz.getSuperclass());
    }
  }

 private void addSetField(Field field) {
    if (isValidPropertyName(field.getName())) {
      setMethods.put(field.getName(), new SetFieldInvoker(field));
      Type fieldType = TypeParameterResolver.resolveFieldType(field, type);
      setTypes.put(field.getName(), typeToClass(fieldType));
    }
  }

  private void addGetField(Field field) {
    if (isValidPropertyName(field.getName())) {
      getMethods.put(field.getName(), new GetFieldInvoker(field));
      Type fieldType = TypeParameterResolver.resolveFieldType(field, type);
      getTypes.put(field.getName(), typeToClass(fieldType));
    }
  }


  /*
  srcType泛型应用到父类泛型上,从而确定泛型
   */
  public static Type resolveFieldType(Field field, Type srcType) {
    //获取字段的声明类型
    Type fieldType = field.getGenericType();
    //获取字段定义所在的类的Class 对象
    Class<?> declaringClass = field.getDeclaringClass();
    return resolveType(
      //Map<K,V>
      fieldType,
      //testType.SubClassA<Long>
      srcType,
      //ClassA
      declaringClass);
  }
private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
    if (type instanceof TypeVariable) {
      return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
    } else if (type instanceof ParameterizedType) {
      return resolveParameterizedType(
        //待解析的ParameterizedType 类型;
        (ParameterizedType) type,
        //解析操作的起始类型testType.SubClassA<Long>
        srcType,
        //定义该字段或方法的类的Class 对象ClassA
        declaringClass);
    } else if (type instanceof GenericArrayType) {
      //根据数组元素类型选择合适的方法进行解析
      return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
    } else {
      return type;//Class 类型
    }
  }

缓存

一级缓存

二级缓存

cache-ref

 private void cacheRefElement(XNode context) {
    if (context != null) {
      //将当前Mapper 配置文件的namespace 与被引用的Cache 所在的namespace 之间的对应关系,记录到Configuration.cacheRefMap 集合中
      configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));
      //创建CacheRefResolver 对象
      CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant, context.getStringAttribute("namespace"));
      try {
        //解析Cache 引用,该过程主要是设置MapperBuilderAssistant 中的currentCache 和unresolvedCacheRef 字段
        cacheRefResolver.resolveCacheRef();
      } catch (IncompleteElementException e) {
        //如解析过程出现异常,则添加到Configuration.incompleteCacheRefs 集合, 稍后再解析
        configuration.addIncompleteCacheRef(cacheRefResolver);
      }
    }
  }
  public Cache resolveCacheRef() {
    return assistant.useCacheRef(cacheRefNamespace);
  }
 public Cache useCacheRef(String namespace) {
    if (namespace == null) {
      throw new BuilderException("cache-ref element requires a namespace attribute.");
    }
    try {
      // 标识未成功解析Cache 引用
      unresolvedCacheRef = true;
      // 获取namespace对应的Cache 对象
      Cache cache = configuration.getCache(namespace);
      if (cache == null) {
        throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.");
      }
      // 记录当前命名空间使用的Cache
      currentCache = cache;
      // 标识已成功解析Cache 引用
      unresolvedCacheRef = false;
      return cache;
    } catch (IllegalArgumentException e) {
      throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.", e);
    }
  }

cache

 private void cacheElement(XNode context) {
    if (context != null) {
     //获取< cache >节点的type ),默认位是PERPETUAL
      String type = context.getStringAttribute("type", "PERPETUAL");
      Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
     //获取< cache > 节点的eviction 属性,默认LRU
      String eviction = context.getStringAttribute("eviction", "LRU");
     //解析eviction 属性指定的Cache 装饰器类型
      Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
      Long flushInterval = context.getLongAttribute("flushInterval");
      Integer size = context.getIntAttribute("size");
      boolean readWrite = !context.getBooleanAttribute("readOnly", false);
      boolean blocking = context.getBooleanAttribute("blocking", false);
     //获取< cache >节点下的子节点,将用于初始化二级缓存
      Properties props = context.getChildrenAsProperties();
     //通过MapperBuilderAssistant 创建Cache 对象,并添加到Configuration . caches 集合中保存
      builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
    }
  }
  public Cache useNewCache(Class<? extends Cache> typeClass,
      Class<? extends Cache> evictionClass,
      Long flushInterval,
      Integer size,
      boolean readWrite,
      boolean blocking,
      Properties props) {
    Cache cache = new CacheBuilder(currentNamespace)
        .implementation(valueOrDefault(typeClass, PerpetualCache.class))
        .addDecorator(valueOrDefault(evictionClass, LruCache.class))
        .clearInterval(flushInterval)
        .size(size)
        .readWrite(readWrite)
        .blocking(blocking)
        .properties(props)
        .build();
   //将Cache 对象添加到Configuration.caches 集合中保存,其中会将Cache 的id 作为key,Cache 对象本身作为value
    configuration.addCache(cache);
   //记录当前命名空间使用的cache 对象
    currentCache = cache;
    return cache;
  }
 public Cache build() {
    /*默认implementation:PerpetualCache
    装饰器集合默认:LruCache*/
    setDefaultImplementations();
    //根据implementation 指定的类型, 通过反射获取参数为String 类型的构造方法,并通过该构造方法创建Cache 对象
    Cache cache = newBaseCacheInstance(implementation, id);
   //初始化Cache 对象
    setCacheProperties(cache);
    // issue #352, do not apply decorators to custom caches

   //检测cache 对象的类型,如果是PerpetualCache 类型,为其添加decorators 集合中的装饰器;
   // 如果是自定义类型的Cache 接口实现,则不添加decorators 集合中的装饰~
    if (PerpetualCache.class.equals(cache.getClass())) {
      for (Class<? extends Cache> decorator : decorators) {
        //通过反射获取参数为Cache 类型的构造方法,并通过该构造方法创建装饰器
        cache = newCacheDecoratorInstance(decorator, cache);
        // 配置cache对象的属性
        setCacheProperties(cache);
      }
      //添加MyBatis中提供的标准装饰器
      cache = setStandardDecorators(cache);
    } else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
      //如果不是LoggingCache 的子类,则添加LoggingCache 装饰器
      cache = new LoggingCache(cache);
    }
    return cache;
  }
 private void setCacheProperties(Cache cache) {
    if (properties != null) {
      // cache 对应的创建MetaObject 对象
      MetaObject metaCache = SystemMetaObject.forObject(cache);
      for (Map.Entry<Object, Object> entry : properties.entrySet()) {
        // 配置项的名称, Cache 对应的属性名称
        String name = (String) entry.getKey();
        // 配置项的值,Cache对应的属性佳
        String value = (String) entry.getValue();
        //检测cache 是否有该属性对应的setter 方法
        if (metaCache.hasSetter(name)) {
          //获取该属性的类型
          Class<?> type = metaCache.getSetterType(name);
          //进行类型转换,并设置该属性值
          if (String.class == type) {
            metaCache.setValue(name, value);
          } else if (int.class == type
              || Integer.class == type) {
            metaCache.setValue(name, Integer.valueOf(value));
          } else if (long.class == type
              || Long.class == type) {
            metaCache.setValue(name, Long.valueOf(value));
          } else if (short.class == type
              || Short.class == type) {
            metaCache.setValue(name, Short.valueOf(value));
          } else if (byte.class == type
              || Byte.class == type) {
            metaCache.setValue(name, Byte.valueOf(value));
          } else if (float.class == type
              || Float.class == type) {
            metaCache.setValue(name, Float.valueOf(value));
          } else if (boolean.class == type
              || Boolean.class == type) {
            metaCache.setValue(name, Boolean.valueOf(value));
          } else if (double.class == type
              || Double.class == type) {
            metaCache.setValue(name, Double.valueOf(value));
          } else {
            throw new CacheException("Unsupported property type for cache: '" + name + "' of type " + type);
          }
        }
      }
    }
    //如果Cache类继承了InitializingObject 接口, 则调用其initialize () 方法继续自定义的初始化操作
    if (InitializingObject.class.isAssignableFrom(cache.getClass())) {
      try {
        ((InitializingObject) cache).initialize();
      } catch (Exception e) {
        throw new CacheException("Failed cache initialization for '"
          + cache.getId() + "' on '" + cache.getClass().getName() + "'", e);
      }
    }
  }

 private Cache setStandardDecorators(Cache cache) {
    try {
      //创建cache 对象对应的MetaObject 对象
      MetaObject metaCache = SystemMetaObject.forObject(cache);
      if (size != null && metaCache.hasSetter("size")) {
        metaCache.setValue("size", size);
      }
        //检测是否指定了clearinterval 字段
      if (clearInterval != null) {
          //添加ScheduledCache 装饰器
        cache = new ScheduledCache(cache);
          // 设置ScheduledCache 的clearInterval 字段
        ((ScheduledCache) cache).setClearInterval(clearInterval);
      }
      //是否只读,对应添加SerializedCache装饰器
      if (readWrite) {
        cache = new SerializedCache(cache);
      }
      //默认添加LoggingCache 和SynchronizedCache 两个装饰器
      cache = new LoggingCache(cache);
      cache = new SynchronizedCache(cache);
      //是否阻塞,对应添加BlockingCache 装饰器
      if (blocking) {
        cache = new BlockingCache(cache);
      }
      return cache;
    } catch (Exception e) {
      throw new CacheException("Error building standard cache decorators.  Cause: " + e, e);
    }
  }

解析crud

 private void buildStatementFromContext(List<XNode> list) {
    if (configuration.getDatabaseId() != null) {
      buildStatementFromContext(list, configuration.getDatabaseId());
    }
    buildStatementFromContext(list, null);
  }
 /**
   * 解析SQL 节点的入口函数
   */
  public void parseStatementNode() {
  //获取SQL节点的id以及databaseId属性,若其databaseid属性值与当前使用的数据库不匹 配,则不加载该SQL 节点;
  //若存在相同id 且databaseid 不为空的SQL 节点,则不再加载该SQL 节点
    String id = context.getStringAttribute("id");
    String databaseId = context.getStringAttribute("databaseId");

    if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
      return;
    }
// 根据SQL 节点的名称决定其SqlCommandType
    String nodeName = context.getNode().getNodeName();
    SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
    boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
    boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
    boolean useCache = context.getBooleanAttribute("useCache", isSelect);
    boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);

    // Include Fragments before parsing
  //在解析SQL 语句之前,先处理其中的< inclu de > 节点
    XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);
    includeParser.applyIncludes(context.getNode());

    String parameterType = context.getStringAttribute("parameterType");
    Class<?> parameterTypeClass = resolveClass(parameterType);

    String lang = context.getStringAttribute("lang");
    LanguageDriver langDriver = getLanguageDriver(lang);

    // Parse selectKey after includes and remove them.
    //解析SQL 节点中的< selectKey>子节 点
    processSelectKeyNodes(id, parameterTypeClass, langDriver);

    // Parse the SQL (pre: <selectKey> and <include> were parsed and removed)
    //完成SQL 节点的解析
    KeyGenerator keyGenerator;
    //获取< selectKey> 节点对应的SelectKeyGenerator的i d
    String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;
    keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true);
    // SQL 节点下存在< selectKey >节点
    if (configuration.hasKeyGenerator(keyStatementId)) {
      keyGenerator = configuration.getKeyGenerator(keyStatementId);
    } else {
      //根据SQL 节点的useGeneratedKeys 属性值、mybatis-config.xml 中全局的useGeneratedKeys
    //配置,以及是否为insert 语句, 决定使用的KeyGenerator 接口实现
      keyGenerator = context.getBooleanAttribute("useGeneratedKeys",
          configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
          ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
    }

    SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
    StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
    Integer fetchSize = context.getIntAttribute("fetchSize");
    Integer timeout = context.getIntAttribute("timeout");
    String parameterMap = context.getStringAttribute("parameterMap");
    String resultType = context.getStringAttribute("resultType");
    Class<?> resultTypeClass = resolveClass(resultType);
    String resultMap = context.getStringAttribute("resultMap");
    String resultSetType = context.getStringAttribute("resultSetType");
    ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);
    if (resultSetTypeEnum == null) {
      resultSetTypeEnum = configuration.getDefaultResultSetType();
    }
    String keyProperty = context.getStringAttribute("keyProperty");
    String keyColumn = context.getStringAttribute("keyColumn");
    String resultSets = context.getStringAttribute("resultSets");

    //这里会检测SQL 节点中是否配置了< selectKey > 节点、SQL 节点的useGeneratedKeys 属性值、
   // mybatis-config.xml 中全局的useGeneratedKeys 配置,以及是否为insert 语句,决定使用的
   // KeyGenerator 接口实现。
//通过MapperBuilderAssistant创建MappedStatement 对象,并添加到
   // Configuration. mappedStatements 集合中保存
    builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
        fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
        resultSetTypeEnum, flushCache, useCache, resultOrdered,
        keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
  }

解析<include> 节点

  public void applyIncludes(Node source) {
    //获取mybatis-config.xml 中< properties > 节点下定义的变量集合
    Properties variablesContext = new Properties();
    Properties configurationVariables = configuration.getVariables();
    Optional.ofNullable(configurationVariables).ifPresent(variablesContext::putAll);
    // 处理<include>子节点
    applyIncludes(source, variablesContext, false);
  }

 private void applyIncludes(Node source, final Properties variablesContext, boolean included) {
    //处理< include >子节点
    if (source.getNodeName().equals("include")) {
      //查找refid属性指向的<sql>节点,返回的是其深克隆的Node对象
      Node toInclude = findSqlFragment(getStringAttribute(source, "refid"), variablesContext);
      //解析<include> 节点下的<property> 节点,将得到的键值对添加到variablesContext 中,并
//形成新的Properties 对象返回,用于替换占位符
      Properties toIncludeContext = getVariablesContext(source, variablesContext);
      //递归处理<include>节点, 在<sql > 节点中可能会使用< include > 引用了其他SQL 片段
      applyIncludes(toInclude, toIncludeContext, true);
      if (toInclude.getOwnerDocument() != source.getOwnerDocument()) {
        toInclude = source.getOwnerDocument().importNode(toInclude, true);
      }
      //将< include >节点替换成< sql >节点
      source.getParentNode().replaceChild(toInclude, source);
      // 将< sql > 节点的子节点添加到< sql >节点前面
      while (toInclude.hasChildNodes()) {
        toInclude.getParentNode().insertBefore(toInclude.getFirstChild(), toInclude);
      }
      // 删除<sql> 节点
      toInclude.getParentNode().removeChild(toInclude);
    } else if (source.getNodeType() == Node.ELEMENT_NODE) {
      //处理SQL节点子节点
      if (included && !variablesContext.isEmpty()) {
        // replace variables in attribute values
        NamedNodeMap attributes = source.getAttributes();
        //遍历当前SQL 语句的子节点
        for (int i = 0; i < attributes.getLength(); i++) {
          Node attr = attributes.item(i);
          attr.setNodeValue(PropertyParser.parse(attr.getNodeValue(), variablesContext));
        }
      }
      NodeList children = source.getChildNodes();
      for (int i = 0; i < children.getLength(); i++) {
        applyIncludes(children.item(i), variablesContext, included);
      }
    } else if (included && (source.getNodeType() == Node.TEXT_NODE || source.getNodeType() == Node.CDATA_SECTION_NODE)
        && !variablesContext.isEmpty()) {
      // replace variables in text node
      //使用之前解析得到的Properties 对象替换对应的占位符
      source.setNodeValue(PropertyParser.parse(source.getNodeValue(), variablesContext));
    }
  }

  private Node findSqlFragment(String refid, Properties variables) {
    refid = PropertyParser.parse(refid, variables);
    //refid=命名空间.refid
    refid = builderAssistant.applyCurrentNamespace(refid, true);
    try {
      //根据refid获取<sql>节点
      XNode nodeToInclude = configuration.getSqlFragments().get(refid);
      return nodeToInclude.getNode().cloneNode(true);
    } catch (IllegalArgumentException e) {
      throw new IncompleteElementException("Could not find SQL statement to include with refid '" + refid + "'", e);
    }
  }

 private Properties getVariablesContext(Node node, Properties inheritedVariablesContext) {
    Map<String, String> declaredProperties = null;
    NodeList children = node.getChildNodes();
    for (int i = 0; i < children.getLength(); i++) {
      Node n = children.item(i);
      if (n.getNodeType() == Node.ELEMENT_NODE) {
        String name = getStringAttribute(n, "name");
        // Replace variables inside
        String value = PropertyParser.parse(getStringAttribute(n, "value"), inheritedVariablesContext);
        if (declaredProperties == null) {
          declaredProperties = new HashMap<>();
        }
        if (declaredProperties.put(name, value) != null) {
          throw new BuilderException("Variable " + name + " defined twice in the same include definition");
        }
      }
    }
    if (declaredProperties == null) {
      return inheritedVariablesContext;
    } else {
      Properties newProperties = new Properties();
      newProperties.putAll(inheritedVariablesContext);
      newProperties.putAll(declaredProperties);
      return newProperties;
    }
  }

解析<selectKey> 节点

  private void processSelectKeyNodes(String id, Class<?> parameterTypeClass, LanguageDriver langDriver) {
    //获取全部的< selectKey> 节点
    List<XNode> selectKeyNodes = context.evalNodes("selectKey");
    //解析< selectKey >节点
    if (configuration.getDatabaseId() != null) {
      parseSelectKeyNodes(id, selectKeyNodes, parameterTypeClass, langDriver, configuration.getDatabaseId());
    }
    parseSelectKeyNodes(id, selectKeyNodes, parameterTypeClass, langDriver, null);
    //移除< selectKey >节点
    removeSelectKeyNodes(selectKeyNodes);
  }

  private void parseSelectKeyNodes(String parentId, List<XNode> list, Class<?> parameterTypeClass, LanguageDriver langDriver, String skRequiredDatabaseId) {
    for (XNode nodeToHandle : list) {
      String id = parentId + SelectKeyGenerator.SELECT_KEY_SUFFIX;
      String databaseId = nodeToHandle.getStringAttribute("databaseId");
      if (databaseIdMatchesCurrent(id, databaseId, skRequiredDatabaseId)) {
        parseSelectKeyNode(id, nodeToHandle, parameterTypeClass, langDriver, databaseId);
      }
    }
  }

 private void parseSelectKeyNode(String id, XNode nodeToHandle, Class<?> parameterTypeClass, LanguageDriver langDriver, String databaseId) {
 //获取< selectKey >节点的result Type 、statement Type 、keyProperty 等属性
    String resultType = nodeToHandle.getStringAttribute("resultType");
    Class<?> resultTypeClass = resolveClass(resultType);
    StatementType statementType = StatementType.valueOf(nodeToHandle.getStringAttribute("statementType", StatementType.PREPARED.toString()));
    String keyProperty = nodeToHandle.getStringAttribute("keyProperty");
    String keyColumn = nodeToHandle.getStringAttribute("keyColumn");
    boolean executeBefore = "BEFORE".equals(nodeToHandle.getStringAttribute("order", "AFTER"));

    // 设置一系列MappedStatement 对象需要的默认配置,例如, useCache 、fetchSize 等
    // defaults
    boolean useCache = false;
    boolean resultOrdered = false;
    KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
    Integer fetchSize = null;
    Integer timeout = null;
    boolean flushCache = false;
    String parameterMap = null;
    String resultMap = null;
    ResultSetType resultSetTypeEnum = null;

    //通过LanguageDriver.createSqlSource ()方法生成SqlSource
    SqlSource sqlSource = langDriver.createSqlSource(configuration, nodeToHandle, parameterTypeClass);
    // <selectKey > 节点中只能配置selectt吾句
    SqlCommandType sqlCommandType = SqlCommandType.SELECT;

    //通过MapperBuilderAssistant 创建MappedStatement 对象,并添加到
    // Configuration.mappedStatements 集合中保存,该集合为StrictMap<MappedStatement > 类型
    builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
        fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
        resultSetTypeEnum, flushCache, useCache, resultOrdered,
        keyGenerator, keyProperty, keyColumn, databaseId, langDriver, null);

    id = builderAssistant.applyCurrentNamespace(id, false);

    MappedStatement keyStatement = configuration.getMappedStatement(id, false);
    //创建< selectKey > 节点对应的KeyGenerator ,添加到Configuration . keyGenerators 集合中
      //保存, Configuration.keyGenerators 字段是StrictMap<KeyGenerator>类型的对象
    configuration.addKeyGenerator(id, new SelectKeyGenerator(keyStatement, executeBefore));
  }


 @Override
  public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {
    XMLScriptBuilder builder = new XMLScriptBuilder(configuration, script, parameterType);
    return builder.parseScriptNode();
  }

  public SqlSource parseScriptNode() {
    //首先判断当前的节点是不是有动态SQL ,动态SQL 会包括占位符或是动态SQL 的相关节点
    MixedSqlNode rootSqlNode = parseDynamicTags(context);
    SqlSource sqlSource;
    //根据是否是动态SQL , 创建相应的SqlSource 对象
    if (isDynamic) {
      sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
    } else {
      sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
    }
    return sqlSource;
  }

 protected MixedSqlNode parseDynamicTags(XNode node) {
    //用于记录生成的SqlNode 集合
    List<SqlNode> contents = new ArrayList<>();
    //获取SelectKey 的所有子节点
    NodeList children = node.getNode().getChildNodes();
    for (int i = 0; i < children.getLength(); i++) {
      //创建XNode ,该过程会将能解析掉的” ${} ” 都解析掉
      XNode child = node.newXNode(children.item(i));
      if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) {
        String data = child.getStringBody("");
        TextSqlNode textSqlNode = new TextSqlNode(data);
        //解析SQL 语句,如果含有未解析的”${}”占位符,则为动态SQL
        if (textSqlNode.isDynamic()) {
          contents.add(textSqlNode);
         // 标记为动态SQL 语句
          isDynamic = true;
        } else {
          contents.add(new StaticTextSqlNode(data));
        }
      } else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628
        //如果子节点是一个标签,那么一定是动态SQL ,并且根据不同的动态标签生成不同的NodeHandler
        String nodeName = child.getNode().getNodeName();
        //根据标签名称获取对应 的NodeHandler 对象
        //处理where之类
        NodeHandler handler = nodeHandlerMap.get(nodeName);
        if (handler == null) {
          throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement.");
        }
        //处理动态SQL ,并将解析得到的SqlNode 对象放入contents 集合中保存
        handler.handleNode(child, contents);
        isDynamic = true;
      }
    }
   // SqlNode 集合包装成一个MixedSqlNode
    return new MixedSqlNode(contents);
  }


  /**
   * 当解析到${}则设置动态
   * @return
   */
  public boolean isDynamic() {
    DynamicCheckerTokenParser checker = new DynamicCheckerTokenParser();
    GenericTokenParser parser = createParser(checker);
    parser.parse(text);
    return checker.isDynamic();
  }

  public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) {
    //调用getSql ()方法,完成SQL 语句的拼接和初步解析
    this(configuration, getSql(configuration, rootSqlNode), parameterType);
  }

  private static String getSql(Configuration configuration, SqlNode rootSqlNode) {
    DynamicContext context = new DynamicContext(configuration, null);
    rootSqlNode.apply(context);
    return context.getSql();
  }
 public DynamicContext(Configuration configuration, Object parameterObject) {
    if (parameterObject != null && !(parameterObject instanceof Map)) {
      //对于非Map 类型的参数,会创建对应的MetaObject 对象,并封装成ContextMap 对象
      MetaObject metaObject = configuration.newMetaObject(parameterObject);
      boolean existsTypeHandler = configuration.getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass());
      bindings = new ContextMap(metaObject, existsTypeHandler);
    } else {
      bindings = new ContextMap(null, false);
    }
    bindings.put(PARAMETER_OBJECT_KEY, parameterObject);
    bindings.put(DATABASE_ID_KEY, configuration.getDatabaseId());
  }
  public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {
    //通过SqlSourceBuilder 完成占住符的解析和替换操作
    SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
    Class<?> clazz = parameterType == null ? Object.class : parameterType;
    sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<>());
  }
 public ParameterMappingTokenHandler(Configuration configuration, Class<?> parameterType, Map<String, Object> additionalParameters) {
      super(configuration);
      this.parameterType = parameterType;
      this.metaParameters = configuration.newMetaObject(additionalParameters);
    }
  public MetaObject newMetaObject(Object object) {
    return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
  }
  public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
    if (object == null) {
    //  若object 为null ,则统一返回SystemMetaObject.NULL_META_OBJECT 这个标志对象
      return SystemMetaObject.NULL_META_OBJECT;
    } else {
      return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
    }
  }

private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
    this.originalObject = object;
    this.objectFactory = objectFactory;
    this.objectWrapperFactory = objectWrapperFactory;
    this.reflectorFactory = reflectorFactory;

    if (object instanceof ObjectWrapper) {
      this.objectWrapper = (ObjectWrapper) object;
    } else if (objectWrapperFactory.hasWrapperFor(object)) {
     //若ObjectWrapperFactory 能够为该原始对象创建对应的ObjectWrapper 对象,则由优先使用ObjectWrapperFactory
//而DefaultObjectWrapperFactory.hasWrapperFor ()始终
//返回false 。用户可以自定义ObjectWrapperFactory 实现进行扩展
      this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
    } else if (object instanceof Map) {
      this.objectWrapper = new MapWrapper(this, (Map) object);
    } else if (object instanceof Collection) {
      this.objectWrapper = new CollectionWrapper(this, (Collection) object);
    } else {
      this.objectWrapper = new BeanWrapper(this, object);
    }
  }
public MappedStatement addMappedStatement(
      String id,
      SqlSource sqlSource,
      StatementType statementType,
      SqlCommandType sqlCommandType,
      Integer fetchSize,
      Integer timeout,
      String parameterMap,
      Class<?> parameterType,
      String resultMap,
      Class<?> resultType,
      ResultSetType resultSetType,
      boolean flushCache,
      boolean useCache,
      boolean resultOrdered,
      KeyGenerator keyGenerator,
      String keyProperty,
      String keyColumn,
      String databaseId,
      LanguageDriver lang,
      String resultSets) {

    if (unresolvedCacheRef) {
      throw new IncompleteElementException("Cache-ref not yet resolved");
    }

    id = applyCurrentNamespace(id, false);
    boolean isSelect = sqlCommandType == SqlCommandType.SELECT;

    MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType)
        .resource(resource)
        .fetchSize(fetchSize)
        .timeout(timeout)
        .statementType(statementType)
        .keyGenerator(keyGenerator)
        .keyProperty(keyProperty)
        .keyColumn(keyColumn)
        .databaseId(databaseId)
        .lang(lang)
        .resultOrdered(resultOrdered)
        .resultSets(resultSets)
        .resultMaps(getStatementResultMaps(resultMap, resultType, id))
        .resultSetType(resultSetType)
        .flushCacheRequired(valueOrDefault(flushCache, !isSelect))
        .useCache(valueOrDefault(useCache, isSelect))
        .cache(currentCache);

    ParameterMap statementParameterMap = getStatementParameterMap(parameterMap, parameterType, id);
    if (statementParameterMap != null) {
      statementBuilder.parameterMap(statementParameterMap);
    }

    MappedStatement statement = statementBuilder.build();
    configuration.addMappedStatement(statement);
    return statement;
  }

 private ParameterMap getStatementParameterMap(
      String parameterMapName,
      Class<?> parameterTypeClass,
      String statementId) {
    parameterMapName = applyCurrentNamespace(parameterMapName, true);
    ParameterMap parameterMap = null;
    if (parameterMapName != null) {
      try {
        parameterMap = configuration.getParameterMap(parameterMapName);
      } catch (IllegalArgumentException e) {
        throw new IncompleteElementException("Could not find parameter map " + parameterMapName, e);
      }
    } else if (parameterTypeClass != null) {
      List<ParameterMapping> parameterMappings = new ArrayList<>();
      parameterMap = new ParameterMap.Builder(
          configuration,
          statementId + "-Inline",
          parameterTypeClass,
          parameterMappings).build();
    }
    return parameterMap;
  }
    public Builder(Configuration configuration, String id, SqlSource sqlSource, SqlCommandType sqlCommandType) {
      mappedStatement.configuration = configuration;
      mappedStatement.id = id;
      mappedStatement.sqlSource = sqlSource;
      mappedStatement.statementType = StatementType.PREPARED;
      mappedStatement.resultSetType = ResultSetType.DEFAULT;
      mappedStatement.parameterMap = new ParameterMap.Builder(configuration, "defaultParameterMap", null, new ArrayList<>()).build();
      mappedStatement.resultMaps = new ArrayList<>();
      mappedStatement.sqlCommandType = sqlCommandType;
      //设置主键生成策略
      mappedStatement.keyGenerator = configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType) ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
      String logId = id;
      if (configuration.getLogPrefix() != null) {
        logId = configuration.getLogPrefix() + id;
      }
      mappedStatement.statementLog = LogFactory.getLog(logId);
      mappedStatement.lang = configuration.getDefaultScriptingLanguageInstance();
    }

最后

以上就是缓慢音响为你收集整理的mybatis源码解析九之整个加载流程解析加载Reader构造SqlSessionFactoryopenSessiongetMapper调用mapper反射缓存解析crud的全部内容,希望文章能够帮你解决mybatis源码解析九之整个加载流程解析加载Reader构造SqlSessionFactoryopenSessiongetMapper调用mapper反射缓存解析crud所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部