Mybatis框架源码Configuration分析

##近期准备做一下Mybatis的源码解读,整个系列大概会有6-7篇文章。
先释放一下目录:
1.Mybatis框架组件设计&顶层接口
2.Mybatis框架启动流程分析
###3.Mybatis框架源码Configuration分析
4.Mybatis框架一条插入语句的执行流程
5.Mybatis框架从源码角度来讲执行增,删,改的时候如何保证线程安全?
6.Mybatis框架一条查询语句的执行流程
7.Mybatis的日志&异常体系
8.Mybatis与Spring集成过程
9.Mybatis的CRUD代码生成
这里是第三篇了,后面会努力更新下去。本章开始着重解读Mybatis框架中的Configuration对象,因为有三个原因:
1.Configuration对象存储了很多Mybatis相关的配置项,
2.Configuration对象存储了mapperConfig.xml解析的结果,XXXDAOMapper.xml解析的结果。
3.为各个顶层接口提供元数据来源。
如果Configuration明白了,Mybatis的血肉就理解清楚了,如果Mybatis的框架组件设计&顶层接口明白了Mybatis的骨架就看清楚了。
下面我从四个方面解读Configuration对象以及背后的数据结构。
##一、Configuration属性解析
###1.Configuration属性解读
ConfigurationClass.png
由于Configuration中的属性太多,这里将其中的属性分为5大类:
1.boolean类型的属性
2.factory类型的属性
3.collection类型的属性
4.registry类型的属性
5.其他辅助边缘的属性
###2.Configuration属性值展示
Configuration属性1.png

Configuration属性2.png

Configuration属性3.png

##二、Configuration中的内部类StrictMap解析
###1.StrictMap的源码内容

 protected static class StrictMap<V> extends HashMap<String, V> {

    private static final long serialVersionUID = -4950446264854982944L;
    private final String name;
    private BiFunction<V, V, String> conflictMessageProducer;

    public StrictMap(String name, int initialCapacity, float loadFactor) {
      super(initialCapacity, loadFactor);
      this.name = name;
    }

    public StrictMap(String name, int initialCapacity) {
      super(initialCapacity);
      this.name = name;
    }

    public StrictMap(String name) {
      super();
      this.name = name;
    }

    public StrictMap(String name, Map<String, ? extends V> m) {
      super(m);
      this.name = name;
    }

    /**
     * Assign a function for producing a conflict error message when contains value with the same key.
     * <p>
     * function arguments are 1st is saved value and 2nd is target value.
     * @param conflictMessageProducer A function for producing a conflict error message
     * @return a conflict error message
     * @since 3.5.0
     */
    public StrictMap<V> conflictMessageProducer(BiFunction<V, V, String> conflictMessageProducer) {
      this.conflictMessageProducer = conflictMessageProducer;
      return this;
    }

    @SuppressWarnings("unchecked")
    public V put(String key, V value) {
      if (containsKey(key)) {
        throw new IllegalArgumentException(name + " already contains value for " + key
            + (conflictMessageProducer == null ? "" : conflictMessageProducer.apply(super.get(key), value)));
      }
      if (key.contains(".")) {
        final String shortKey = getShortName(key);
        if (super.get(shortKey) == null) {
          super.put(shortKey, value);
        } else {
          super.put(shortKey, (V) new Ambiguity(shortKey));
        }
      }
      return super.put(key, value);
    }

    public V get(Object key) {
      V value = super.get(key);
      if (value == null) {
        throw new IllegalArgumentException(name + " does not contain value for " + key);
      }
      if (value instanceof Ambiguity) {
        throw new IllegalArgumentException(((Ambiguity) value).getSubject() + " is ambiguous in " + name
            + " (try using the full name including the namespace, or rename one of the entries)");
      }
      return value;
    }

2.源码解读
StrictMap继承了HashMap,为什么这么做呢,类里多了一个name,也就是说自带注解的HashMap,同时简单重写了get,put方法。
我们可以看一下Configuration如何应用这个子类:
StrictMap.png

有很多框架会重写JDK中的集合类,做一些特别的处理,但是我们可以把这种取巧的或者骚操作应用到自己写的业务代码或者组件代码中。这也算是学到用到了。
##三、Configuration中每个集合属性背后的数据结构
###1.collection类型的属性解读
Map<String, MappedStatement> mappedStatements;QQ截图20200705135645.pngMap<String, ResultMap> resultMaps;QQ截图20200705135716.pngMap<String,ParameterMap> parameterMaps;QQ截图20200705135740.pngMap<String, XNode> sqlFragments;QQ截图20200705135804.png
###2.注册表类型的属性解读
MapperRegistry mapperRegistry;mapperRegistry.pngTypeHandlerRegistry typeHandlerRegistry;TypeHandlerRegistry.pngTypeAliasRegistry typeAliasRegistry;TypeAliasRegistry.pngLanguageDriverRegistry languageRegistry;LanguageDriverRegistry.png
总体上可以看到用Map用的比较多,用map可以通过不同的key迅速找到对应的value。
##四、Configuration背后的数据结构关系
1.Configuration和其他类的关系
Configuration.png
这里做一个解读:
Configuration:包括很多配置属性,是全局类型的.代表配置类的总集
MapperRegistry:以map的形式存储映射代理工厂MapperProxyFactory,这个代理工厂其实就是代表每个XXDAOMapper.xml和对应的DAO Interface.
MapperProxyFactory:以map的形式存储MapperMethod,这里的MapperMethod就是XXDAOMapper.xml中的CRUD方法。
MapperMethod:存储方法映射,是源数据配置。
Configuration>MapperRegistry>MapperProxyFactory>MapperMethod,通过这样的map配置映射可以看明白xml配置和源码之间的关系。
上图中可以从<>线去看,以Configuration为开始,从MapperMethod到SqlSession形成整个回路。整体从源码跟进去就能看明白,从mapperconfig.xml到XXDAOMapper.xml,再到XXDAOMapper.xml中的方法三层间接map嵌套。到这里整个Configuration的源码解读就结束了。

猜你喜欢

转载自blog.csdn.net/u010504064/article/details/107280413
今日推荐