Mybatis的解析和运行原理
Posted Demrystv
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis的解析和运行原理相关的知识,希望对你有一定的参考价值。
Mybatis的解析和运行原理
Mybatis的运行过程大致分为两大步:第一步,读取配置文件缓存到Configuration对象,用以创建 SqlSessionFactory;第二步,SqlSession的执行过程。其中第一步中, SqlSessionFactory的创建过程比较简单,第二步中, SqlSession的执行过程较为复杂,其底层需要用到反射技术和动态代理的知识。
1. 构建 SqlSessionFactory过程
SqlSessionFactory是Mybatis的核心类之一,其重要的功能是提供创建Mybatis的核心接口 SqlSession,所以要先创建 SqlSessionFactory,在Mybatis中,它采用了 Builder的模式去创建 SqlSessionFactory,在实际中可以通过 SqlSessionFactoryBuilder 去构建,其构建分为两步:
第1步:通过org.apache.ibatis.builder.xml.XMLConfiguration解析配置的XML 文件,读出所配置的参数,并将读取的内容存入到org.apache.ibatis.session.Configuration类对象中。而Configuration对象采用的是单例模式,几乎所有的Mybatis配置内容都会存放在这个单例对象中,以便后续将这些内容读出。
第2步:使用Configuration对象去创建SqlSessionFactory,Mybatis中的SqlSessionFactory是一个接口,而不是一个实现类,为此Mybatis提供了一个默认的实现类org.apache.ibatis.session.defaults.DefaultSqlSessionFactory。在大部分情况下都没必要自己去创建新的SqlSessionFactory实现类。
这种创建方式就是一种Builder模式,对于复杂的对象而言,使用构造参数很难实现,这时使用一个类(比如Configuration)作为统领,一步步构建所需的内容,然后通过他去创建最终的对象(比如SqlSessionFactory),这样比较清晰,思路值得我们去学习和参考。
1.1 构建Configuration
在SqlSessionFactory构建中,configuration是最重要的,它的作用是:
①读入配置文件,包括基础配置的XML和映射器XML(或注解)。
②初始化一些基础配置,比如Mybatis的别名等,一些重要的类对象(比如插件、映射器、Object工厂、typeHandlers对象等)。
③提供单例,为后续创建SessionFactory服务,提供配置的参数。
④执行一些重要对象的初始化方法。
Configuration是通过XMLConfigurationBuilder去构建的,首先它会读出所有XML配置的信息,然后把他们解析并保存在Configuration单例中。它会对如下内容进行初始化:全局参数、别名、插件、对象工厂、对象包装工厂、反射工厂、环境设置、数据库环境、数据库标识、类型转换器和映射器等等。
1.2 构建映射器的内部组成
当XMLConfigBuilder解析XML时,会将每一个SQL和其配置的内容保存起来。一般而言,在Mybatis中一条SQL和它配置信息主要由3个部分组成,分别是MappedStatement、SqlSource和BoundSql
①MappedStatement的作用是保存一个映射器节点的内容,它是一个类,包括配置的SQL、SQL中的id、缓存信息、resultType、resultMap等配置内容,它还有一个重要的属性sqlSource。
②SqlSource是提供BoundSql的地方,它是MappedStatement的一个属性,它的作用是根据上下文和参数解析生成需要的SQL。
③BoundSql是一个结果对象,也就是SqlSource通过对SQL和参数的联合解析得到的SQL和参数。
1.3 构建SqlSessionFactory
SqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
Mybatis会根据文件流先生成Configuration对象,进而构建SqlSessionFactory对象。
2.SqlSession运行过程
2.1映射器(Mapper)的动态代理
在程序的编写过程中,我们经常写这样的代码:
RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class);
通过看Mybatis的源码可以得知,它是运用了configuration对象的getMapper方法,来获取对应的接口的对象的,其底层又运用了映射器的注册器MapperRegistry来获取对应的接口对象,首先它判断是否注册一个Mapper,如果没有则会抛出异常信息,如果有,就会启用MapperProxyfactory工厂来生成一个代理实例。Mapper映射是通过动态代理来实现的,这里可以看到动态代理对接口的绑定,它的作用是生成动态代理对象(占位),而代理的方法则是放到了MapperProxy类中。在看MapperProxy的源码,可以发现invoke的方法逻辑。如果Mapper是一个JDK动态代理对象,那么它就会运行到invoke方法里面。invoke首先判断是否是一个类,这里mapper是一个接口不是类,所以判定失败,然后生成MapperMethod对象,它是通过cachedMapperMethod方法对其初始化。最后执行execute方法,把sqlSession和当前运行的参数传递进去。
通过分析源码我们可以得知,Mybatis为什么只用Mapper接口就能运行了,因为mapper的XML文件的命名空间对应的是这个接口的全限定名,而方法就是那条SQL的id,这样Mybatis就可以根据全路径和方法名,将其和代理对象绑定起来。通过动态代理技术,让这个接口运行其阿里,后面采用命令模式。最后使用SqlSession接口的方法是的它能够执行对应的SQL,只有有了这层封装,就可以采用接口编程。
2.2 SqlSession的四大对象
①Executor代表执行器,由它调度StatementHandler、ParameterHandler、ResultSetHandler等来执行对应的SQL,其中StatementHandler是最重要的。
②StatementHandler的作用是使用数据库的Statement执行操作,它是四大对象的核心,起到承上启下的作用,许多重要的插件都是通过拦截它来实现的。
③ParameterHandler是用来处理SQL参数的。
④ResultSetHandler是进行数据集的封装返回处理的。
以上是关于Mybatis的解析和运行原理的主要内容,如果未能解决你的问题,请参考以下文章