前言
我们开始从mybatis 启动流程开始阅读源码
mybatis
的配置信息层次结构:
configuration
properties
settings
typeAliases
typeHandlers
objectFactory
objectWrapperFactory
reflectorFactory
plugins
environments
transactionManager
dataSource
databaseIdProvider
mappers
无论是结合 Spring
使用 Mybatis
还是单独使用,在启动的时候都需要经过这个入口 SqlSessionFactoryBuilder
来构建 SqlSessionFactory
使用 SqlSessionFactoryBuilder
构建 SqlSessionFactory
有两种方:编码方式,Xml 配置方式;
获取 SqlSessionFactory
的主体调用流程如下:
org.apache.ibatis.session.SqlSessionFactoryBuilder#build(Reader or InputStream);
org.apache.ibatis.builder.xml.XMLConfigBuilder#XMLConfigBuilder();
org.apache.ibatis.builder.xml.XMLConfigBuilder#parse
org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration
org.apache.ibatis.session.SqlSessionFactoryBuilder#build(org.apache.ibatis.session.Configuration)
得到的 SqlSessionFactory
的默认实现 DefaultSqlSessionFactory
编码方式这里不做赘述, 配置文件的方式主要流程如下得到 Configuration
xml 配置方式主要依赖 XMLConfigBuilder
来解析配置文件
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
//解析 xml 中 <properties> 标签,主要是解析url 和 resource, 需要注意的是这两个配置不能同时存在
propertiesElement(root.evalNode("properties"));
// 注册 type aliase 可以使用 package 扫描一个文件夹中的所有 带@Alias 注解的所有类
// [注意] alias 会忽略大小写 toLowCase
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
// MyBatis uses an `ObjectFactory` to create all needed new Objects.
objectFactoryElement(root.evalNode("objectFactory"));
//
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectionFactoryElement(root.evalNode("reflectionFactory"));
settingsElement(root.evalNode("settings"));
// read it after objectFactory and objectWrapperFactory issue #631
//
environmentsElement(root.evalNode("environments"));
// 通过xml 中设置的type 别名构建 DatabaseIdProvider, 默认为 VendorDatabaseIdProvider
// 再通过 DatabaseIdProvider 获取 databaseId, 设置到 Configuration.databaseId
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
// TypeHander 对应一个 Class 以及一个 JdbcType
// 注册 TypeHander 时可以一个个的注册,也可以注册一个 package 中所有实现了 `TypeHandler` 接口的类
// 通过继承 BaseTypeHandler 自定义的TypeHander
// TypeHandler 如果没有通过 @MappedJdbcTypes 指定的JdbcType 则为null
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
mybatis 的重要组成部分是 mapper xml 文件,对于这些文件的解析很重要
解析 package 中的接口时,获取 package 下的所有接口, 依次直接使用 MapperRegister
注册 Interface –> MapperProxyFactory
使用 mapperClass
配置接口信息, 也是 MapperRegister
注册 Interface –> MapperProxyFactory
使用 url
或 resource
配置 mapper xml 文件的路径, 使用 XmlMappperBuilder
解析 xml 文件
这里先介绍 MapperRegister
MapperProxyFactory
MapperRegister
中保存了 Interface –> MapperProxyFactory 的map
mybatis
中大量使用了设计模式, MapperProxyFactory
使用了工厂模式MapperProxyFactory
一看就是生产 MapperProxy
的工厂类, 提供 org.apache.ibatis.binding.MapperProxyFactory#newInstance(org.apache.ibatis.session.SqlSession)
方法获取 Mapper Interface 的实现类
MapperProxy
是java 动态代理的使用,MapperProxy
实现了 InvocationHandler
接口
1 | /** |
Configuration
: mybatis 配置信息的根节点
public Configuration() {
// 这里注册了很多类的别名,在需要的时候通过反射机制获取 类的实例
typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
typeAliasRegistry.registerAlias("LRU", LruCache.class);
typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
// 注册语言管理驱动,默认语言管理驱动为:`XMLLanguageDriver`
languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
languageRegistry.register(RawLanguageDriver.class);
}
ObjectFactory
:
Reflector
ObjectWrapper
TransactionFactory
TypeAliasRegistry
LanguageRegistry