Mybatis 源码探究 (3)创建 SqlSessionFactory对象

时隔许久,终于又能接着来搞他啦。Mybatis 一起来探究吧。

先笑会再进入主题吧

开始啦

一、new SqlSessionFactoryBuilder().build(inputStream) 方法

String resource="mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
public SqlSessionFactory build(InputStream inputStream) {//在这里又接着调用了重载方法build 我们接着往下走啊 return build(inputStream, null, null);
}

二、SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) 方法

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {try {//XMLConfigBuilder是对mybatis的配置文件进行解析的类,会对myabtis解析后的信息存放在Configuration对象中XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);// 下面这句到重点啦return build(parser.parse());} catch (Exception e) {throw ExceptionFactory.wrapException("Error building SqlSession.", e);} finally {ErrorContext.instance().reset();try {inputStream.close();} catch (IOException e) {// Intentionally ignore. Prefer previous error.}}
}

一个一个讲啊,慢慢来。

1、 new XMLConfigBuilder(inputStream, environment, properties);

XMLConfigBuilder : 翻译过来就是XML配置器

XMLConfigBuilder是对mybatis的配置文件进行解析的类,会对myabtis解析后的信息存放在Configuration对象中,Configuration对象

会贯穿整个mybatis的执行流程,为mybatis的执行过程提供各种需要的配置信息。

public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}

XPathParser 和 XMLMapperEntityResolver 不是主要研究对象,我放在了文章最后,好奇的话,可以先滑到文末去看。

三、build(parser.parse()) 方法

先看parser.parse()方法 它的返回对象是核心配置对象Configuration

public Configuration parse() {if (parsed) {throw new BuilderException("Each XMLConfigBuilder can only be used once.");}parsed = true;parseConfiguration(parser.evalNode("/configuration"));return configuration;
}

进入到parseConfiguration(parser.evalNode("/configuration"))方法

可以看到 在这里就是将我们配置的好的文件 一步一步解析封装到Configuration对象去。

 private void parseConfiguration(XNode root) {try {// issue #117 read properties firstpropertiesElement(root.evalNode("properties"));Properties settings = settingsAsProperties(root.evalNode("settings"));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 #631environmentsElement(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);}}

这一段代码主要作用就是将所有的配置文件加载到给定的对象。

我对于研究这个非常不熟练,结果就是走不出来。

mapperElement(root.evalNode("mappers"))里面要研究的东西不少,先略过哈。

四、return build(parser.parse()); 回到我们的入口处

我们可以知道 parser.parse() 构建出了一个 Configuration 对象,并成为了build()方法的入参。

这个build(parser.parse());

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

这个地方就是将之前已经赋值好的Configuration 放在里面

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

课间休息

地点:长沙

五、SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

至此 我们获得了 SqlSessionFactory 对象,我们可以通过这获取到mybatis操作数据库的 SqlSession 对象。

 SqlSession sqlSession = sessionFactory.openSession();

openSession() 是SqlSessionFactory 接口下的方法

public interface SqlSessionFactory {SqlSession openSession();SqlSession openSession(boolean autoCommit);SqlSession openSession(Connection connection);SqlSession openSession(TransactionIsolationLevel level);SqlSession openSession(ExecutorType execType);SqlSession openSession(ExecutorType execType, boolean autoCommit);SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);SqlSession openSession(ExecutorType execType, Connection connection);Configuration getConfiguration();
}

我们这里调用的方法是这个哈

  @Overridepublic SqlSession openSession() {// openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);}

最后一个参数就是是否提交,如果不为true,我们做了修改or删除,数据库并不会修改or删除。

接着往下看:

  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {Transaction tx = null;try {final Environment environment = configuration.getEnvironment();final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);final Executor executor = configuration.newExecutor(tx, execType);return new DefaultSqlSession(configuration, executor, autoCommit);} catch (Exception e) {closeTransaction(tx); // may have fetched a connection so lets call close()throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);} finally {ErrorContext.instance().reset();}}

最后返回mybatis操作数据库的 SqlSession 对象。

六、MyUserMapper mapper = sqlSession.getMapper(MyUserMapper.class);

  /**检索映射器。参数:type – 映射器接口类类型参数:<T> – 映射器类型返回:绑定到此 SqlSession 的映射器*/<T> T getMapper(Class<T> type);

接下来开始套娃哈

我们实际调用的是它的实现类里的方法:

@Override
public <T> T getMapper(Class<T> type) {return configuration.getMapper(type, this);
}

你看又牵扯到configuration对象了哈,知道它多重要了吧。

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {return mapperRegistry.getMapper(type, sqlSession);
}

到了mapperRegistry 这个对象拉。 mapperRegistry的翻译就是映射器注册表 这个地方我目前还没有搞懂它是什么时候注册进去的哈。

  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {// 这里是去获得 我们传过来的 MyUserMapper.class的代理类的final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);if (mapperProxyFactory == null) {throw new BindingException("Type " + type + " is not known to the MapperRegistry.");}try {return mapperProxyFactory.newInstance(sqlSession);} catch (Exception e) {throw new BindingException("Error getting mapper instance. Cause: " + e, e);}}

接下来继续看这个 mapperProxyFactory.newInstance(sqlSession) 方法

  public T newInstance(SqlSession sqlSession) {final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);return newInstance(mapperProxy);}

接着套丫

  protected T newInstance(MapperProxy<T> mapperProxy) {return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);}

当我们看到这里的时候就知道mybatis是通过反射和代理来进行这些操作的哈。

真实执行对象并不在,而是在 MapperProxy mapperProxy Mapper的代理对象中。

那个具体执行的,等下一篇博客哈。我还有很多没懂的。

七、XPathParser

public class XPathParser {private final Document document;private boolean validation;private EntityResolver entityResolver;private Properties variables;private XPath xpath;
}
  • Document(Document对象)

    Document 对象代表整个 XML 文档,是一棵文档树的根,可为我们提供对文档数据的最初(或最顶层)的访问入口。

  • validation(是否开启验证标记)

    该标记表示设置解析器在解析文档的时候是否校验文档,在创建DocumentBuilderFactory实例对象时进行设置。

  • EntityResolver (加载本地的DTD文件

    如果解析mybatis-config.xml 配置文件,默认联网加载http://mybatis.org/dtd/mybatis-3- config.dtd 这个DTD 文档,当网络比较慢时会导致验证过程缓慢。在实践中往往会提前设置EntityResolver 接口对象加载本地的DTD 文件,从而避免联网加载DTD文件。

  • XPath (XPath对象)

    XPath 是一种为查询XML 文档而设计的语言,它可以与DOM 解析方式配合使用,实现对XML 文档的解析。

  • variables(配置参数集合)。

    对应配置文件中节点下定义的键值对集合,包括通过url或者resource读取的键值对集合。

八、XMLMapperEntityResolver

对这个我没有深究。doc注释就是这么一句话:MyBatis DTD 的离线实体解析器 说实话DTD都是我第一次见

Mybatis 源码探究 (3)创建 SqlSessionFactory对象 执行sqlSession.getMapper()方法相关推荐

  1. Mybatis 源码探究 (4) 将sql 语句中的#{id} 替换成 ‘?

    Mybatis 源码探究 (4) 将sql 语句中的#{id} 替换成 '? 出于好奇,然后就有了这篇文章啦. 源码给我的感觉,是一座大山的感觉.曲曲折折的路很多,点进去就有可能出不来. 不过慢慢看下 ...

  2. Spring AOP源码(2)—AspectJAwareAdvisorAutoProxyCreator创建代理对象【两万字】

      基于最新Spring 5.x,介绍了Spring AOP中的AspectJAwareAdvisorAutoProxyCreator自动代理创建者的工作流程,对于创建代理对象的源码进行了深度分析! ...

  3. 单元测试源码分析之一创建mock对象

    之前已经介绍过Mockito和PowerMock的常见用法,PowerMock其实就是在Mockito的基础上使用了字节码技术使得其可以对静态方法,私有方法等进行插桩. 现在就先来看看Mockito是 ...

  4. aop源码分析之 —— 创建代理对象

    前言 在上一篇我们分析了AOP生成代理对象的源码流程,我们知道,springaop中,生成代理对象一般有2种,当目标对象实现了接口时,默认使用JDK代理,否则就采用cglib代理,而且,最终调用目标对 ...

  5. MyBatis 源码解读-会话创建过程

    这是第二步, 我们跟数据库的每一次连接, 都需要创建一个会话, 我们用openSession()方法来创建. DefaultSqlSessionFactory -- openSessionFromDa ...

  6. Mabatis 源码探究(2)Java 获取mybatis-config.xml的输入流 inputStream对象

    关于Mybatis源码探究的专栏. 其我的专业是软件技术这个方向的,mybatis 许久以前就学了,但是心里一直存在一些疑惑.也上网查了,看过各种大佬的博客,对 于Mybatis的理解始终感觉不足.最 ...

  7. 为什么想要去探究Mybatis源码?(1)

    为什么想要去探究Mybatis源码?(1) 关于Mybatis源码探究的专栏. 其我的专业是软件技术这个方向的,mybatis 许久以前就学了,但是心里一直存在一些疑惑.也上网查了,看过各种大佬的博客 ...

  8. Mybatis源码学习(三)SqlSession详解

    前言 上一章节我们学习了SqlSessionFactory的源码,SqlSessionFactory中的方法都是围绕着SqlSession来的.,那么SqlSession又是什么东东呢?这一章节我们就 ...

  9. Mybatis日志源码探究

    一.项目搭建 1.pom.xml <dependencies><dependency><groupId>log4j</groupId><artif ...

最新文章

  1. AMD 和 Intel 之战:CPU 哪家强?
  2. Python学习前的计划
  3. 自学python需要下载什么软件-一个零基础学习Python应该知道的学习步骤与规划
  4. 浅议数据中心规划设计阶段暖通系统节能措施
  5. FarPoint 应用总结
  6. OpenGL生成的法线贴图并增加光照
  7. python如何绘制曲线图_python怎么画曲线图
  8. c语言如何将程序保存在文件,急求如何将下列C语言程序数据存储到文件中?
  9. python visual studio pandas_pandas DataFrame索引行列的实现
  10. AFNnetworking详解
  11. dial tcp xxx: connectex: A connection attempt failed
  12. Eclipse中如何更改字体大小?
  13. 《First Order Motion Model for Image Animation》论文解读
  14. python不会英语不会数学怎么自学-26岁了,自学Python怎么样?
  15. java流程图怎么画_JAVA流程图怎么画
  16. 开源项目推荐:office办公软件,绘图软件
  17. 软件开发方法的过程、特点、优缺点
  18. k620显卡 unreal_Modo三维建模系统_搜维尔[SouVR.com]—专业虚拟现实、增强现实、智能智造产品和解决方案超市...
  19. Swift 模式(Patterns)
  20. Javascript匿名类

热门文章

  1. CALL TRANSACTION 小节
  2. 批次管理的质量跟踪案例分享_食品加工行业
  3. 探讨BI可视化下的旅游大数据分析,你的钱都花哪了?
  4. 干货:5个维度构建电商全景大数据分析
  5. 抢跑直播电商双11,快手电商帝国雏形初显
  6. mysql数据库没启动命令_mysql数据库服务启动和停止命令介绍(转载)
  7. 不会但一定要了解的方面,python列表解析方式
  8. Python中比元组更好用的namedtuple
  9. 基于Django的乐观锁与悲观锁解决订单并发问题的一点浅见
  10. Intel Realsense D435 pyrealsense2 get_option_range() 获取rs.option中参数值取值范围 获取默认值