mybatis 源码阅读(一)

前言

我们开始从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

使用 标签中的 urlresource 配置 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
* Copyright 2009-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.binding;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.ibatis.session.SqlSession;

/**
* @author Lasse Voss
*/
public class MapperProxyFactory<T> {

// MapperProxy 代理的 Mapper 接口
private final Class<T> mapperInterface;
// 这里的Key 是 Mapper 接口中方法对象,Value 是方法对象的封装
private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>();

public MapperProxyFactory(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}

public Class<T> getMapperInterface() {
return mapperInterface;
}

public Map<Method, MapperMethod> getMethodCache() {
return methodCache;
}


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

// 通过 Sqlsession 获取 Mapper 接口
public T newInstance(SqlSession sqlSession) {
final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}

}

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