Mybatis3源码分析(代码分析git地址)
1. 项目层级图
2.主要内容
2.1annotations(注解)
annotations部分主要定义的是mybatis使用的各种注解。如@select,@delete,@update,@insert等,所有如下图。
注解的源码里面也注释了,这些注解怎么使用具体如下图。
注
:@;
转义为@
2.1binding(sql绑定)
2.1.1Mapper注册类
其中主要的操作逻辑都是围绕着knownMappers
展开的,knownMappers
定义如下
private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();
config
其中config是mybatis的配置和一些资源的挂载类还要一些其他作用,这里展示先不展开讲述,由于篇幅限制。
private final Configuration config;
2.1.1.1addMapper方法逻辑(代码分析git地址)
public <T> void addMapper(Class<T> type) {
if (type.isInterface()) {//判断mapper是不是接口,因为底层使用的是JDK动态代理,JDK代理是基于接口的。
if (hasMapper(type)) {//判断这个mapper是否已经注册
//已经注册报错
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
//加载是否完成标识符
boolean loadCompleted = false;
try {
//knownMappers存放一个以 type为k,new MapperProxyFactory<>(type)(将新生成的type类型的mapper代理工厂类)为V
knownMappers.put(type, new MapperProxyFactory<>(type));
// It's important that the type is added before the parser is run
// otherwise the binding may automatically be attempted by the
// mapper parser. If the type is already known, it won't try.
//生成MapperAnnotationBuilder用于解析mapper相关的xml和注解
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();
//解析完成 加载完成标识符为true
loadCompleted = true;
} finally {
if (!loadCompleted) {//判断加载是否完成 未完成移除本次添加
knownMappers.remove(type);
}
}
}
}
MapperAnnotationBuilder 生成分析
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
其中config
是mybatis的配置和一些资源的挂载类,type
是该mapper的全限定名。
MapperAnnotationBuilder
类字段
构造类主要初始化了configuration
,assistant
,type
public MapperAnnotationBuilder(Configuration configuration, Class<?> type) {
//通过全限定名推出 该类的资源地址
String resource = type.getName().replace('.', '/') + ".java (best guess)";
//mapper建造助手类
this.assistant = new MapperBuilderAssistant(configuration, resource);
//配置类
this.configuration = configuration;
//类型
this.type = type;
}
statementAnnotationTypes
是一个注解类型的静态常量set集合
private static final Set<Class<? extends Annotation>> statementAnnotationTypes = Stream
.of(Select.class, Update.class, Insert.class, Delete.class, SelectProvider.class, UpdateProvider.class,
InsertProvider.class, DeleteProvider.class)
.collect(Collectors.toSet());
MapperAnnotationBuilder 的parse()过程
parser.parse();
点击查看
public void parse() {
String resource = type.toString();
if (!configuration.isResourceLoaded(resource)) { //配置类中该资源未被加载进行加载
//加载mapper相对于的xml 以及解析xml中mapper的内容
loadXmlResource();
//配置类 中添加resource的记录 便于判断是否改资源已经加载
configuration.addLoadedResource(resource);
//将类名作为命名空间
assistant.setCurrentNamespace(type.getName());
//解析是否要缓存命名空间 与类一对一
parseCache();
//解析是否要缓存命名空间引用 与类 一对多
parseCacheRef();
//代理mapper方法
for (Method method : type.getMethods()) {
if (!canHaveStatement(method)) {
//是桥接或者default方法不进行代理
continue;
}
//@Select和@SelectProvider的方法进行解析
//并且改方法上不存在@ResultMap注解
if (getAnnotationWrapper(method, false, Select.class, SelectProvider.class).isPresent()
&& method.getAnnotation(ResultMap.class) == null) {
//缺失@ResultMap情况下的 解析
parseResultMap(method);
}
try {
//解析动态sql Statement JDBC的Statement,PreStatement都是Statement(此次不止解析Statement还解析了方法上的 @Options存储等系列方法上的注解)
parseStatement(method);
} catch (IncompleteElementException e) {
//解析出行异常 下文parsePendingMethods()会对解析出行异常的再次解析
configuration.addIncompleteMethod(new MethodResolver(this, method));
}
}
}
//解析失败的方法重新 解析
parsePendingMethods();
}