SSM-Mybatis-运行原理和解析-构建SqlSessionFactory过程
构建SqlSessionFactory过程
它是听Builder模式创建的,实际可以通过SqlSessionFactoryBuilder去构建,构建分为两步:
-
通过org.apache.ibatis.builder.xml.XMLConfigBuilder解析配置的XML文件,将读取的内容存入到org.apache.ibatis.session.Configuration类对象中,它是一个单例模式,
-
使用Configuration对象去创建SqlSessionFactory,SqlSessionFactory是一个接口,因此Mybatis提供了一个默认实现类org.apache.ibatis.session.defaults.DefaultSqlSessionFactory,大部分情况下不需要创建实现类
这是一种Builder创建方式,对于复杂的对象创建,使用构造器很难实现,使用一个类(Configuration)作为统领,一步步构建,然后通过它创建最终对象(SqlSessionFactory)
例如:在XMLConfigBuilder中一段代码:
private void parseConfiguration(XNode root) {
try {
this.propertiesElement(root.evalNode("properties"));
Properties settings = this.settingsAsProperties(root.evalNode("settings"));
this.loadCustomVfs(settings);
this.loadCustomLogImpl(settings);
this.typeAliasesElement(root.evalNode("typeAliases"));
this.pluginElement(root.evalNode("plugins"));
this.objectFactoryElement(root.evalNode("objectFactory"));
this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
this.reflectorFactoryElement(root.evalNode("reflectorFactory"));
this.settingsElement(settings);
this.environmentsElement(root.evalNode("environments"));
this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
this.typeHandlerElement(root.evalNode("typeHandlers"));//使用这行说明
this.mapperElement(root.evalNode("mappers"));
} catch (Exception var3) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
}
}
上面代码是通过一步步解析XML的内容得到对应的信息,这些信息是配置文件中的内容,使用typeHandler解析方法说明,配置的typeHandler会被注册到typeHandlerRegistry对象中,该对象在XMLConfigBuilder的父类BaseBuilder
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();//此处得知是通过Configuration获取的
}
...
}
typeHandlerRegistry实际就是Configuration单例的一个属性,可以通过Configuration获取typeHandlerRegistry
构建Configuration
Configuration的作用:
- 读入配置文件,包括基础配置的XML和映射器XML(注解)
- 初始化一些基础配置,如:Mybatis别名等,一些重要的类对象(插件,映射器,Object工厂,typeHandler对象等)
- 提供单例:为后续创建SqlSessionFactory服务,提供配置参数
- 执行一些重要对象的初始化方法
构建映射器的内部组成
当XMLConfigBuilder解析XML时,会将每一个SQL和其配置文件的内容保存起来,Mybatis中一条SQL和它相关配置信息由3个部分组成:
- MapperdStatement:保存一个映射器节点(select insert detele update)的内容,他是一个类保存了配置的信息,有一个属性很重要:sqlSoutce,通过它可以读取某条SQL配置的所有信息
- SqlSoutce:是提供BoundSql对象的地方,是MapperdStatement一个属性,它是一个接口,有几个重要的实现类:DynamicSqlSource,ProviderSqlSource,RawSqlSource,StaticSqlSource,作用是根据上下文和参数解析生成需要的SQL
- BoundSql:是一个结果对象,是SQLSoutce通过对SQL和参数的联合解析得到的SQL和参数,是建立SQL和参数的地方,有三个常用属性:sql,parameterObject,parameterMappings
注意:MapperdStatement涉及的东西比较多,一般不建议修改它,容易产生错误;SqlSource是一个接口,主要作用根据参数和其他的规则组装SQL,Mybatis本身已经实现了他们,一般也不需要修改;对于最终的参数和SQL都反应在BoundSql类对象上,在插件中需要拿到他才能拿到当前运行的SQL和参数,从而对运行过程做出修改,满足特殊要求
BoundSql的三个重要属性:
- parameterObject:参数本身,可以传递简单对象,POJO或Map,注解@Param注解参数,他的一些规则:
- 传递简单的对象,包括int double string 等,传入时候会把基本类型进行自动类型转换
- 传递POJO或者Map,parameterObject就是传入POJO或者Map
- 传递多个参数,如果没有@Param注解,那么Mybatis会把parameterObject变为一个Map<String,Object>对象,其键值的关系是按顺序来规划
- 使用@Param注解,Mybatis会把parameterObject变成一个Map<String,Object>,只是把其数字的键值置换成@Param注解键值
- parameterMappings:是一个List,他的每一个元素都是parameterMapping对象,对象描述参数,通过它可以实现参数和SQL结合,以便Prepared Statement能通过它找他更好的parameterObject对象的属性设置参数。
- sql:属性就是书写在映射器里面的一条被SqlSource解析后的SQL
构建SqlSessionFactory
SqlSessionFactory =new SqlSessionFactoryBuilder().build(inputStream);
Mybatis会根据文件流创建Configuration对象,而进构建SqlSessionFactory对象。