mybatis3.5.x源码系列

Posted xxzblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis3.5.x源码系列相关的知识,希望对你有一定的参考价值。

  1. 首先我们了解一下mybatis中的几个核心概念
  • Configuration 配置,可以理解为mybatis的大管家,管理一切
  • Environment 环境,这个主要负责数据源,事务管理器
  • MappedStatement mapper.xml对应的声明类,定义mapper中所有的标签,属性
  • MapperRegistry Mapper注册器,管理编写的mapper类和mapper.xml
  • InterceptorChain 拦截器链,管理所有拦截器,也就是我们常用的mybatis插件
  • SqlSessionFactory SQL会话管理工厂类
  • SqlSession SQL会话,定义了增,删,改,查,提交,回滚,获取java.sql.Connection,获取mapper
  • Executor 执行器,主要负责增,删,改,查,提交,回滚的执行
  • MapperProxy mapper代理类,生成接口代理对象

带着上面的概念,我们开始我们的源码分析入门之旅

  1. 首先我们要看看官方demo 打开mybatis-3-getting-started

例子:

代码结构:

src
  main
    test
      java
        io.jsbxyyx
          mapper
            Blog.java
            BlogMapper.java
            BlogMapper.xml
          Demo.java
          mybatis-config.xml
public static void main(String[] args) throws IOException 
    String resource = "io/jsbxyyx/mybatis-config.xml";
    InputStream inputStream = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    BlogMapper blogMapper = sqlSessionFactory.openSession().getMapper(BlogMapper.class);
    Blog blog = blogMapper.selectBlog(1L);
    System.out.println(blog);

XML创建SqlSessionFactory

org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream, java.lang.String, java.util.Properties)
  》org.apache.ibatis.builder.xml.XMLConfigBuilder#parse()
    》org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration(org.apache.ibatis.parsing.XNode root)
  》org.apache.ibatis.session.SqlSessionFactoryBuilder#build(org.apache.ibatis.session.Configuration)

核心方法org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration

该方法会解析出properties,settings,typeAliases,plugins,objectFactory,objectWrapperFactory,reflectorFactory,environments,databaseIdProvider,typeHandlers,mappers

解析mappers

// 这里解析mappers下的package标签,也就是包扫描,以及mapper标签
org.apache.ibatis.builder.xml.XMLConfigBuilder#mapperElement(org.apache.ibatis.parsing.XNode parent)
  》org.apache.ibatis.builder.xml.XMLStatementBuilder#parseStatementNode
    》org.apache.ibatis.builder.MapperBuilderAssistant#addMappedStatement

解析mappers,创建MappedStatement并缓存到内存

打开session

org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
  》org.apache.ibatis.session.Configuration#getDefaultExecutorType()
  》org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource(org.apache.ibatis.session.ExecutorType execType, org.apache.ibatis.session.TransactionIsolationLevel level, boolean autoCommit)
    》org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#getTransactionFactoryFromEnvironment(org.apache.ibatis.mapping.Environment)
  》org.apache.ibatis.transaction.TransactionFactory#newTransaction(javax.sql.DataSource, org.apache.ibatis.session.TransactionIsolationLevel, boolean)
    》org.apache.ibatis.transaction.jdbc.JdbcTransaction#JdbcTransaction(javax.sql.DataSource, org.apache.ibatis.session.TransactionIsolationLevel, boolean)
  》org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)
  》org.apache.ibatis.session.defaults.DefaultSqlSession#DefaultSqlSession(org.apache.ibatis.session.Configuration, org.apache.ibatis.executor.Executor, boolean)

流程

获取数据源 =》开启事务 =》获取执行器 =》创建SqlSession

获取Mapper

org.apache.ibatis.session.Configuration#getMapper(java.lang.Class<T>, org.apache.ibatis.session.SqlSession)
    》org.apache.ibatis.binding.MapperRegistry#getMapper(java.lang.Class<T>, org.apache.ibatis.session.SqlSession)
      》org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession)
        》java.lang.reflect.Proxy#newProxyInstance(java.lang.ClassLoader loader, java.lang.Class<?>[] interfaces, java.lang.reflect.InvocationHandler h)

流程

根据接口class =》创建JDK动态代理对象org.apache.ibatis.binding.MapperProxy(这就是为啥mybatis的mapper定义是接口的原因)

执行方法

io.jsbxyyx.mapper.BlogMapper#selectBlog
  》org.apache.ibatis.binding.MapperProxy#invoke
    》org.apache.ibatis.binding.MapperProxy#cachedInvoker
      》org.apache.ibatis.binding.MapperMethod#MapperMethod(java.lang.Class<?> mapperInterface, java.lang.reflect.Method method, org.apache.ibatis.session.Configuration config)
      》org.apache.ibatis.binding.MapperProxy.PlainMethodInvoker#invoke
        》org.apache.ibatis.binding.MapperMethod#execute(org.apache.ibatis.session.SqlSession, java.lang.Object[] args)
          》org.apache.ibatis.session.Configuration#getMappedStatement(java.lang.String statement)
          》org.apache.ibatis.executor.Executor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
            》org.apache.ibatis.executor.CachingExecutor#createCacheKey(org.apache.ibatis.mapping.MappedStatement, java.lang.Object parameterObject, org.apache.ibatis.session.RowBounds, org.apache.ibatis.mapping.BoundSql)
              》org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
                》org.apache.ibatis.executor.BaseExecutor#queryFromDatabase(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
                  》org.apache.ibatis.executor.SimpleExecutor#doQuery(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.mapping.BoundSql)
                    》org.apache.ibatis.executor.statement.RoutingStatementHandler#RoutingStatementHandler(org.apache.ibatis.executor.Executor, org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.mapping.BoundSql)
                      》org.apache.ibatis.session.Configuration#newParameterHandler(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.mapping.BoundSql)
                        》org.apache.ibatis.scripting.LanguageDriver#createParameterHandler
                        》org.apache.ibatis.plugin.InterceptorChain#pluginAll(parameterHandler)
                      》org.apache.ibatis.session.Configuration#newResultSetHandler(org.apache.ibatis.executor.Executor, org.apache.ibatis.mapping.MappedStatement, org.apache.ibatis.session.RowBounds, org.apache.ibatis.executor.parameter.ParameterHandler, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.mapping.BoundSql)
                        》org.apache.ibatis.executor.resultset.DefaultResultSetHandler
                        》org.apache.ibatis.plugin.InterceptorChain#pluginAll(resultSetHandler)
                      》org.apache.ibatis.plugin.InterceptorChain#pluginAll(statementHandler)
                    》org.apache.ibatis.executor.SimpleExecutor#prepareStatement(org.apache.ibatis.executor.statement.StatementHandler, org.apache.ibatis.logging.Log)
                      》org.apache.ibatis.transaction.Transaction#getConnection
                        》org.apache.ibatis.transaction.jdbc.JdbcTransaction#openConnection
                    》org.apache.ibatis.executor.statement.StatementHandler#query(java.sql.Statement, org.apache.ibatis.session.ResultHandler)
                      》java.sql.PreparedStatement#execute
                      》org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets(java.sql.Statement)

流程

动态代理MapperProxy =》创建MappedStatement缓存key =》获取Executor =》分别加载parameter,resultSet,statement插件 =》 获取java.sql.Connection =》获取java.sql.Statement =》执行sql =》处理结果集

流程结束。

期待下次更新咯。😄

以上是关于mybatis3.5.x源码系列的主要内容,如果未能解决你的问题,请参考以下文章

MyBatis源码分析一.JDBC回顾

造轮子系列转轮选择工具——WheelView

一起talk C栗子吧(第一百三十七回:C语言实例--查看环境变量)

Spark源码分析之四:Stage提交

Dubbo学习系列之十(Sentinel之限流与降级)

Eureka 系列(02)客户端源码分析