1.SqlSessionFactoryBuilder 

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
SqlSessionFactory var5;
try {//通过XML
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
var5 = this.build(parser.parse());
} catch (Exception var14) {
throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
} finally {
ErrorContext.instance().reset(); try {
inputStream.close();
} catch (IOException var13) {
;
} } return var5;
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}

2.BaseBuilder

public abstract class BaseBuilder {
protected final Configuration configuration;
protected final TypeAliasRegistry typeAliasRegistry;
protected final TypeHandlerRegistry typeHandlerRegistry; public BaseBuilder(Configuration configuration) {
this.configuration = configuration;
this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();
this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();
}
...
}

3.XMLConfigBuilder extends BaseBuilder

public Configuration parse() {
if (this.parsed) {
throw new BuilderException("Each MapperConfigParser can only be used once.");
} else {
this.parsed = true;
this.parseConfiguration(this.parser.evalNode("/configuration"));
return this.configuration;
}
} private void parseConfiguration(XNode root) {
try {
this.propertiesElement(root.evalNode("properties"));
this.typeAliasesElement(root.evalNode("typeAliases"));
this.pluginElement(root.evalNode("plugins"));
this.objectFactoryElement(root.evalNode("objectFactory"));
this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
this.settingsElement(root.evalNode("settings"));
this.environmentsElement(root.evalNode("environments"));
this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
this.typeHandlerElement(root.evalNode("typeHandlers"));
//解析mappers指定的映射文件,将MapperStatement信息加载至configuration
this.mapperElement(root.evalNode("mappers"));
} catch (Exception var3) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
}
}

根据指定mapper映射文件的方式对mappers标签进行解析

<mappers>

  <mapper resource="com/abc/dao/mapper.xml"/>

</mappers>

<mappers>

  <mapper url="file:///E:\workspace\com/abc/dao/mapper.xml"/>

</mappers>

<mappers>

  <mapper class="com.abc.dao.IStudentDao"/>

</mappers>

<mappers>

  <mapper package="com.abc.dao"/>

</mappers>

private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
Iterator i$ = parent.getChildren().iterator(); while(true) {
while(i$.hasNext()) {
XNode child = (XNode)i$.next();
String resource;
if ("package".equals(child.getName())) {
resource = child.getStringAttribute("name");
this.configuration.addMappers(resource);
} else {
resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
XMLMapperBuilder mapperParser;
InputStream inputStream;
if (resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
inputStream = Resources.getResourceAsStream(resource);
mapperParser = new XMLMapperBuilder(inputStream, this.configuration, resource, this.configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url != null && mapperClass == null) {
ErrorContext.instance().resource(url);
inputStream = Resources.getUrlAsStream(url);
mapperParser = new XMLMapperBuilder(inputStream, this.configuration, url, this.configuration.getSqlFragments());
mapperParser.parse();
} else {
if (resource != null || url != null || mapperClass == null) {
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
} Class<?> mapperInterface = Resources.classForName(mapperClass);
this.configuration.addMapper(mapperInterface);
}
}
} return;
}
}
}

4.Configuration & MapperRegistry

public class Configuration {
protected MapperRegistry mapperRegistry; //存储每个接口的mapper文件对应的类
protected final Map<String, MappedStatement> mappedStatements; //存储由namespace 和sql id 能唯一确定的
  sql语句对应的sql节点信息
...
}
public class MapperRegistry {
private Configuration config;
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap(); public MapperRegistry(Configuration config) {
this.config = config;
} public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
} else {
try {
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception var5) {
throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
}
}
} public <T> boolean hasMapper(Class<T> type) {
return this.knownMappers.containsKey(type);
} public <T> void addMapper(Class<T> type) {
if (type.isInterface()) {
if (this.hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
} boolean loadCompleted = false; try {
this.knownMappers.put(type, new MapperProxyFactory(type));
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(this.config, type);
parser.parse();
loadCompleted = true;
} finally {
if (!loadCompleted) {
this.knownMappers.remove(type);
}
}
}
}
}

 

5.建造者模式

一个对象的参数太过于复杂,就不再适于通过构造函数的方式创建对象,而通过建造者模式对该对象的每个参数分别组建

6.DefaultSqlSession和DefaultSqlSessionFactory

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null; DefaultSqlSession var8;
try {
Environment environment = this.configuration.getEnvironment();
TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
Executor executor = this.configuration.newExecutor(tx, execType, autoCommit);
var8 = new DefaultSqlSession(this.configuration, executor);
} catch (Exception var12) {
this.closeTransaction(tx);
throw ExceptionFactory.wrapException("Error opening session. Cause: " + var12, var12);
} finally {
ErrorContext.instance().reset();
} return var8;
}

  

mybatis 源码分析一的更多相关文章

  1. MyBatis源码分析-MyBatis初始化流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  2. MyBatis源码分析-SQL语句执行的完整流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  3. MyBatis源码分析(5)——内置DataSource实现

    @(MyBatis)[DataSource] MyBatis源码分析(5)--内置DataSource实现 MyBatis内置了两个DataSource的实现:UnpooledDataSource,该 ...

  4. MyBatis源码分析(4)—— Cache构建以及应用

    @(MyBatis)[Cache] MyBatis源码分析--Cache构建以及应用 SqlSession使用缓存流程 如果开启了二级缓存,而Executor会使用CachingExecutor来装饰 ...

  5. MyBatis源码分析(3)—— Cache接口以及实现

    @(MyBatis)[Cache] MyBatis源码分析--Cache接口以及实现 Cache接口 MyBatis中的Cache以SPI实现,给需要集成其它Cache或者自定义Cache提供了接口. ...

  6. MyBatis源码分析(2)—— Plugin原理

    @(MyBatis)[Plugin] MyBatis源码分析--Plugin原理 Plugin原理 Plugin的实现采用了Java的动态代理,应用了责任链设计模式 InterceptorChain ...

  7. 【MyBatis源码分析】select源码分析及小结

    示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...

  8. MyBatis源码分析之环境准备篇

    前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...

  9. Mybatis源码分析-BaseExecutor

    根据前文Mybatis源码分析-SqlSessionTemplate的简单分析,对于SqlSession的CURD操作都需要经过Executor接口的update/query方法,本文将分析下Base ...

  10. Mybatis源码分析-StatementHandler

    承接前文Mybatis源码分析-BaseExecutor,本文则对通过StatementHandler接口完成数据库的CRUD操作作简单的分析 StatementHandler#接口列表 //获取St ...

随机推荐

  1. leetcode感想

    想想要参加秋招了,重新开始刷leetcode,记录一下自己在过程遇到的问题. 算法优化: 1.合并if分支. 2.将所有可以直接给出结果的特殊情况放在最前面直接返回.

  2. 洛谷P1439 【模板】最长公共子序列

    题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最长公共子 ...

  3. qtp type和set方法的区别

    type模拟键盘输入,是一个字符一个字符的输入. set是整个输入框一起置值. 例如:winedit中输入a后,再用type输入b,结果就是ab 如果用set输入a后,再用set输入b,结果就是b. ...

  4. python(列表2)

    1.remove(删除指定值的元素) x = ['to','be','or','not','to','be'] x.remove('be') x ['to','or','not','to','be'] ...

  5. 关于javascript中arguments的一个很好的例子

    金克斯的迫击炮! 实现一个摧毁(destroyer)函数,第一个参数是待摧毁的数组,其余的参数是待摧毁的值 函数中的有隐式的不确定个数的参数,而我们在函数中将会用到它,很显然,这需要我们在 argum ...

  6. 一个通过GINA拦截 盗窃登陆口令的病毒分析

    病毒行为: 1\将资源中的DLL释放到当前目录下 2\设置注册表,将GINA DLL设置为上一步中释放的DLL DLL行为: 1\在DLL被进程装载时, 装载正常的msgina.dll, 并保存句柄, ...

  7. Python-接口自动化(六)

    接口基础知识(六) (七)接口 1.接口:外部系统与本系统之间以及系统内部的各个子系统间,以约定标准提供的服务,包括对外提供的接口/对外提供的接口. 不同的请求协议:http  webservice  ...

  8. 逐帧动画抖动、适配布局、SVG Sprites

    笔者所在的前端团队主要从事移动端的H5页面开发,而团队使用的适配方案是: viewport units + rem.具体可以参见凹凸实验室的文章 – 利用视口单位实现适配布局 . 笔者目前(2017. ...

  9. Windows Server 2008 R2 服务器系统安装及配置全过程图文详解

    前言 本文主要介绍了 windows Server 2008 R2 服务器系统的安装及相关配置. 介绍的是以优盘的方式安装. 写这篇博文的目的一来是为了供有需要的网友参考, 二来自己也在此做个记载. ...

  10. 前端校验框架ValidForm之check方法修正

    用过validform的朋友相信都知道,在利用check方法的时候,发现该方法对表单输入值只要符合datatype规则的就返回ture.那么我们想对某个字段进行ajax重复校验的时候,只需要在该表单元 ...