ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Mybatis源码分析:BaseBuilder

2019-08-02 22:55:09  阅读:302  来源: 互联网

标签:alias color BaseBuilder 别名 类型 源码 hljs Mybatis null


<style></style> <style></style>

BaseBuilder源码分析

BaseBuilder是mybatis配置文件,Mapper文件等解析器的基类,该类为抽象类,但并未声明相关的抽象方法,所有子类都可以使用BaseBuilder所提供的属性字段和实现方法,BaseBuilder下的每个子类在使用构造器实例化时,必定会调用BaseBuilder的构造方法,这是因为BaseBuilder内部维护着三个属性Configuration,TypeAliasRegistry,TypeHandlerRegistry。Configuration本身是一个"大杂烩",内部维护着各种各样的对象实例。TypeAliasRegistry,TypeHandlerRegistry就是其中两个,事实上,BaseBuilder的这两个实例就是从Configuration获取的,为什么要这样做呢?在编写mybatis配置文件时,有时候需要自定义参数别名和类型处理器,在解析配置文件的过程中,必须将自定义的别名处理器重新放入Configuration中。

属性及构造器代码段

   //配置类
  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();
  }

 

BaseBuilder提供了较多的基础方法,下面列出了一些基础的方法(代码过于简单,省略)和较为重要的方法。

方法名参数名作用
parseExpression regex,defaultValue 获取正则表达式对象,如果regex表达式为null,则使用默认值defaultValue作为表达式
booleanValueOf value,defaultValue 获取value的boolean值,如果为null,则使用默认值defaultValue
integerValueOf value,defaultValue 获取整形value值,如果为null,则使用默认值defaultValue
stringSetValueOf value,defaultValue 获取value的值,按照‘,’分割为数组并转为hashset,如果value为null,则使用默认值defaultValue
resolveJdbcType alias 根据别名查询对应的JDBC数据类型,JdbcType是mybatis对java.sql.Types的一次包装,并且是个枚举类,详细的信息可以查看org.apache.ibatis.type.JdbcType
resolveResultSetType alias 根据别名获取对应的结果集,详细信息参照org.apache.ibatis.mapping.ResultSetType。该类是对java.sql.ResultSet的包装,java.sql.ResultSet提供了三个值。
ResultSet.TYPE_FORWORD_ONLY 结果集的游标只能向下滚动。
ResultSet.TYPE_SCROLL_INSENSITIVE 结果集的游标可以上下移动,当数据库变化时,当前结果集不变。
ResultSet.TYPE_SCROLL_SENSITIVE 返回可滚动的结果集,当数据库变化时,当前结果集同步改变。
resolveParameterMode alias 根据别名获取ParameterMode类型,可选值为IN, OUT, INOUT,详细信息可参照org.apache.ibatis.mapping.ParameterMode类

BaseBuilder有两个比较重要的方法createInstance(String alias) 根据别名实例化对象,resolveTypeHandler(Class<?> javaType, String typeHandlerAlias) 根据类型处理器别名和java类解析出类型处理器,首先看createInstance方法。

createInstance方法:用于根据别名创建实例对象,如果别名为null,那么直接返回null对象,否则根据别名所找到的类进行实例化,在下列代码中,根据调用链发现是BaseBuilder下的 typeAliasRegistry调用了resolveAlias()方法。
前面说过typeAliasRegistry是直接从Configuration对象中获取的,那么Configuration会直接初始化一个TypeAliasRegistry对象,查找org.apache.ibatis.type.TypeAliasRegistry的构造器,可以发现注册了大量的基础数据类型,再看看 typeAliasRegistry.resolveAlias()方法。该方法首先根据别名去已注册的别名集合TYPE_ALIASES中查找对应的类,如果不存在,则使用Resources.classForName(string)获取对应的类,现在只需要知道Resources.classForName的效果跟Class.forname()的效果一样,用于根据类路径返回类对象即可。后续会分析Resources对象。

 1   protected Object createInstance(String alias) {
 2     Class<?> clazz = resolveClass(alias);
 3     if (clazz == null) {
 4       return null;
 5     }
 6     try {
 7       return resolveClass(alias).newInstance();
 8     } catch (Exception e) {
 9       throw new BuilderException("Error creating instance. Cause: " + e, e);
10     }
11   }
12 
13   protected Class<?> resolveClass(String alias) {
14     if (alias == null) {
15       return null;
16     }
17     try {
18       return resolveAlias(alias);
19     } catch (Exception e) {
20       throw new BuilderException("Error resolving class. Cause: " + e, e);
21     }
22   }
23   protected Class<?> resolveAlias(String alias) {
24         return typeAliasRegistry.resolveAlias(alias);
25       }

 

resolveAlias()方法

 1  public <T> Class<T> resolveAlias(String string) {
 2     try {
 3       if (string == null) {
 4         return null;
 5       }
 6       // issue #748
 7       String key = string.toLowerCase(Locale.ENGLISH);
 8       Class<T> value;
 9       if (TYPE_ALIASES.containsKey(key)) {
10         value = (Class<T>) TYPE_ALIASES.get(key);
11       } else {
12         value = (Class<T>) Resources.classForName(string);
13       }
14       return value;
15     } catch (ClassNotFoundException e) {
16       throw new TypeException("Could not resolve type alias '" + string + "'.  Cause: " + e, e);
17     }
18   }

 

resolveTypeHandler:用于根据类型别名创建对应的类型处理器,跟别名处理器类似,首先根据别名类型是否为null进行判断,再去别名注册器中寻找别名对应的类类型,使用类类型在类型处理注册器中寻找类类型对应的实例,如果不存在该实例,则采用反射对其进行实例化。下面是创建类型处理器的流程分析。可以看到,无论是什么类型,想要使用别名,必须向别名注册器中进行注册以获的<别名,类类型>对应关系。如果是类类型,还需向类型处理别名注册器中注册一个<类类型,处理器实例>的映射关系。

  • 判断类型处理器别名是否为null,如果为null值,则直接返回null对象,否则在别名注册器中寻找已经注册的类类型
  • 如果找到的类类型不为null并且不属于TypeHandler类型,则抛出BuilderException异常
  • 将寻找到的类类型强转为TypeHandler类型,在类型处理器中根据类类型寻找已经注册的类型处理器实例
  • 如果无法找寻到对应的类型处理器实例,则采用反射进行实例化。

 

参照文档

标签:alias,color,BaseBuilder,别名,类型,源码,hljs,Mybatis,null
来源: https://www.cnblogs.com/zhengzuozhanglina/p/11291553.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有