MyBatis-底层源码解析-(详细),韩顺平java从入门到精通课件

loadCustomLogImpl(settings);
/**

  • 解析 typeAliases配置文件
    */
    typeAliasesElement(root.evalNode(“typeAliases”));

/**

  • 解析 plugins 配置文件
  • 这个是插件,可以动态的拦截sql执行
    */
    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
    environmentsElement(root.evalNode(“environments”));
    databaseIdProviderElement(root.evalNode(“databaseIdProvider”));
    typeHandlerElement(root.evalNode(“typeHandlers”));

/**

  • 加载 mapper.xml 文件
    */
    mapperElement(root.evalNode(“mappers”));
    } catch (Exception e) {
    throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
    }

1.4.1: mapperElement(root.evalNode(“mappers”));

解析mapper.xml文件,以及接口方法的注解

public class XMLConfigBuilder extends BaseBuilder {
/**

  • mapper隐射文件解析
  • @param parent
  • @throws Exception
    /
    private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
    for (XNode child : parent.getChildren()) {
    /
    *
  • 解析 <package

/
if (“package”.equals(child.getName())) {
String mapperPackage = child.getStringAttribute(“name”);
/
*

  • 添加所有包下的接口
  • 实际调用 configuration.addMapper(mapperInterface);
    /
    configuration.addMappers(mapperPackage);
    } else {
    String resource = child.getStringAttribute(“resource”);
    String url = child.getStringAttribute(“url”);
    String mapperClass = child.getStringAttribute(“class”);
    /
    *
  • 解析 <mapper resource
  • <mappers>
    
  •     <mapper resource="mapper/UserMapper.xml"/>
    
  • </mappers>
    

/
if (resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
InputStream inputStream = Resources.getResourceAsStream(resource);
/
*

  • mapper.xml 解析器
    /
    XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
    /
    *
  • 开始解析 mapper.xml文件
  • 重点分析这个 同样也会调用 configuration.addMapper(mapperInterface); 这个方法
    /
    mapperParser.parse();
    } else if (resource == null && url != null && mapperClass == null) {
    /
    *
  • 解析 <mapper url
    /
    ErrorContext.instance().resource(url);
    InputStream inputStream = Resources.getUrlAsStream(url);
    XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
    mapperParser.parse();
    } else if (resource == null && url == null && mapperClass != null) {
    /
    *
  • 解析 <mapper class
    /
    Class<?> mapperInterface = Resources.classForName(mapperClass);
    configuration.addMapper(mapperInterface);
    } else {
    /
    *
  • 以下代码可以看出 url resource class 三个属性只能选择一个,否则就会报错
    */
    throw new BuilderException(“A mapper element may only specify a url, resource or class, but not more than one.”);
    }
    }
    }
    }
    }
    }

1.4.2:mapperParser.parse();解析

我的UserMapper.xml文件内容为:

<?xml version="1.0" encoding="UTF-8"?> select * from `user` where userId = #{userId}

UserMapper接口内容为:

package com.mapper;

import com.entity.User;
import org.apache.ibatis.annotations.Select;

public interface UserMapper {
@Select(“select * from user where userId = 2”)
User findById(int userId);
}

疑问?UserMapper.xml有<select id=“findById”,而在接口中的findById方法我又加了一个@Select注解;那么执行会选择哪一条Sql执行还是报错呢?

以UserMapper.xml为例子解析,可以看到 resource = mapper/UserMapper.xml
在这里插入图片描述

public class XMLMapperBuilder extends BaseBuilder {
public void parse() {
if (!configuration.isResourceLoaded(resource)) {
/**

  • 解析 mapper.xml文件内容
    /
    configurationElement(parser.evalNode("/mapper"));
    configuration.addLoadedResource(resource);
    /
    *
  • 解析 mapper.xml的
  • namespace指定的{UserMapper}接口的注解信息
    */
    bindMapperForNamespace();
    }

parsePendingResultMaps();
parsePendingCacheRefs();
parsePendingStatements();
}
}

1.4.3:configurationElement(parser.evalNode("/mapper"));

解析 mapper.xml文件内容

public class XMLMapperBuilder extends BaseBuilder {
private void configurationElement(XNode context) {
try {
/**

  • namespace属性
    /
    String namespace = context.getStringAttribute(“namespace”);
    if (namespace == null || namespace.equals("")) {
    /
    *
  • 不指定 namespace会报错哦 由此得知 namespace属性是必须指定的
    /
    throw new BuilderException(“Mapper’s namespace cannot be empty”);
    }
    builderAssistant.setCurrentNamespace(namespace);
    /
    *
  • 解析 cache-ref
    /
    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"));
    /
    *
  • 解析 sql语句 select|insert|update|delete
  • 重点分析这里,这里的解析会关联到 mapper接口的执行方法 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);
    }
    }
    }

1.4.4:buildStatementFromContext(context.evalNodes(“select|insert|update|delete”));

解析 sql语句 select|insert|update|delete;list参数内容是select|insert|update|delete的Sql语句

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值