当前位置:首页 > 话题广场 > 攻略专题 > 游戏问答

如何初始化接口?终于找到答案了MyBatis初始化加载 Mapper 接口与XML文件

在MyBatis初始化过程中,大致有以下几个步骤:分解所有IT类编制

创建Configuration全局配置对象时,TypeAliasRegistry别名注册中心将添加Mybatis所需的相关类,并将基于语言的默认类设置为加载XMLLanguageDriver的myba配置文件、Mapper界面的详图索引信息和XML映射文件。解析的配置信息构成相应的对象,并存储在Configuration全局配置对象中。构建DefaultSqlSessionFactory对象可以创建DefaultSqlSession对象。MyBatis的SqlSession的默认实现类在整个初始化过程中包含更多代码。

由于在《MyBatis初始化(一)之加载myba》 《MyBatis初始化(二)之加载Mapper接口与XML映射文件》 《MyBatis初始化(三)之SQL初始化(上)》 《MyBatis初始化(四)之SQL初始化(下)》 MyBatis初始化期间解析Mapper接口与XML映射文件相关的篇幅很多,XML映射文件的解析过程也很复杂,因此分为以下三个模块,逐步分析,易于理解。

初始化(b)加载映射接口和映射文件

上一个模块分析了如何解析myba配置文件。最后,尚未分析解析Mapper/标签的方法。这个过程比较复杂,因为需要解析映射程序接口和XML映射文件。让我们看一下这个解析过程

解析XML映射文件生成的对象主要如下图所示。

默认程序包路径:org.a、org.a

主要涉及的类:

Org.a.XML.XMLConfigBuilder:解析配置文件,开始初始化Mapper接口和XML映射文件,创建Configuration全局配置对象org.a:Mapper接口注册中心,Mapper这里我们解析的Mapper接口是org . a . apperorg.a.XML.XMLMapperBuilder:剖析XML映射文件org.a.xml.XMLStatementBuilder:剖析XML Delete/insert/标签)org.a. mapperbuilderassistant也就是说,Java类型和JDBC类型之间的映射信息org.a.ResultMap: resultMap/标记的配置信息和存储子标记的所有信息org.a.MappedStatement:解析select/upps

让我们回顾一下前面的模块。org.a.xml.XMLConfigBuilder解析myba配置文件中的mapper/标记,并调用parse()-parse configuration(xnode roon)

private void mapper element(xnode parent)throws exception {

If(零件!=空){

//0通过子节点

For (xnodechild3360 ()) {

//1如果是package标签,请扫描包

If ('package ')。equal(){

//获取软件包名称

字串mapper package=c(' name ');

//添加到配置

CON(MAPPERPACKAGE);

}如果是else {//mapper标签

获取//resource、URL和class属性

string resource=c(' resource ');

字串URL=c(' URL ');

字串mapper class=c(' class ');

//2使用相对于类路径的资源引用

If(资源!=null URL==null mapper class==null){

ErrorCon()。资源(资源);

从//resource导入InputStream对象

Inputstream inputstream=re(资源);

//创建XMLMapperBuilder对象

xmlmapperbuildermapperparser=new xmlmapperbuilder(input stream、configuration、resource、con());

//执行解决

MA();

//3使用完全限定的资源定位器(URL)

} else if (resource==空URL!=空映射类==空){

ErrorCon()。资源(URL);

获取//URL的InputStream对象

InputStream InputStream=Re(URL);

//创建XMLMapperBuilder对象

xmlmapperbuildermapperparser=new xmlmapperbuilder(input stream、configuration、URL、con());

//执行解决

MA();

//4使用映射程序接口实现类的完全限定类名

} else if(resource==null URL==null mapper class!=空){

//Mapper接口导入

班级?mapper interface=Re(mapper class);

//添加到配置

地图界面(con);

} else {

throw new builder exception(' a mapper element may only specify a URL,resource or class,but not more than one . '));

}

}

}

}

}

遍历Mapper/标记的子节点

对于Package/子节点,导入解析包路径下Mapper接口的Package属性后,通过子节点的resource属性或URL属性解析映射文件,或通过class属性解析Mapper接口,通常会直接配置包路径,因此可以看到上面的第一对

首先,将软件包软件包路径添加到Configuration全局配置对象中。也就是说,通过调用调用内部MapperRegistry注册表和MapperRegistry的addMappers(字符串包名)方法进行注册

让我们看一下如何在MapperRegistry注册表中解析。此类在上一文档的Binding模块中解释如下:

Public class MapperRegistry {

public void add mappers(string package name){

Addmappers(软件包名称,object . class);

}

/* *

*用于在指定软件包中搜索Mapper接口并将其绑定到XML文件

* @since 3.2.2

*/

public void add mappers(string package name,class?SuperType) {

//1搜索指定程序包下的指定类

ResolverUtilClass?ResolverUtil=new ResolverUtil();

Re (new re (supertype),package name);

SetClass?Extends Class?MapperSet=re();

//2巡回,添加到knownMappers

For(类?MapperClass : mapperSet) {

add mapper(mapper class);

}

}

public t void add mapper(class type){

//1判断,必须是接口。


if ()) {
// <2> 已经添加过,则抛出 BindingException 异常
if (hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
// <3> 将Mapper接口对应的代理工厂添加到 knownMappers 中
knownMa(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.
// <4> 解析 Mapper 的注解配置
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
// 解析 Mapper 接口上面的注解和 Mapper 接口对应的 XML 文件
();
// <5> 标记加载完成
loadCompleted = true;
} finally {
// <6> 若加载未完成,从 knownMappers 中移除
if (!loadCompleted) {
knownMa(type);
}
}
}
}
}

<1>首先必须是个接口

<2>已经在MapperRegistry注册中心存在,则会抛出异常

<3>创建一个Mapper接口对应的MapperProxyFactory动态代理工厂

<4>【重要!!!】通过MapperAnnotationBuilder解析该Mapper接口与对应XML映射文件

MapperAnnotationBuilder

org.a.annotation.MapperAnnotationBuilder:解析Mapper接口,主要是解析接口上面注解,加载XML文件会调用XMLMapperBuilder类进行解析

我们先来看看他的构造函数和parse()解析方法:

public class MapperAnnotationBuilder {
/**
* 全局配置对象
*/
private final Configuration configuration;
/**
* Mapper 构造器小助手
*/
private final MapperBuilderAssistant assistant;
/**
* Mapper 接口的 Class 对象
*/
private final Class<?> type;
public MapperAnnotationBuilder(Configuration configuration, Class<?> type) {
String resource = ().replace('.', '/') + ".java (best guess)";
= new MapperBuilderAssistant(configuration, resource);
= configuration;
= type;
}
public void parse() {
String resource = ();
if (!con(resource)) {
// 加载该接口对应的 XML 文件
loadXmlResource();
con(resource);
a(());
// 解析 Mapper 接口的 @CacheNamespace 注解,创建缓存
parseCache();
// 解析 Mapper 接口的 @CacheNamespaceRef 注解,引用其他命名空间
parseCacheRef();
Method[] methods = ();
for (Method method : methods) {
try {
// issue #237
if (!me()) { // 如果不是桥接方法
// 解析方法上面的注解
parseStatement(method);
}
} catch (IncompleteElementException e) {
con(new MethodResolver(this, method));
}
}
}
parsePendingMethods();
}
private void loadXmlResource() {
// Spring may not know the real resource name so we check a flag
// to prevent loading again a resource twice
// this flag is set at XMLMapperBuilder#bindMapperForNamespace
if (!con("namespace:" + ())) {
String xmlResource = ().replace('.', '/') + ".xml";
// #1347
InputStream inputStream = ("/" + xmlResource);
if (inputStream == null) {
// Search XML mapper that is not in the module but in the classpath.
try {
inputStream = Re(), xmlResource);
} catch (IOException e2) {
// ignore, resource is not required
}
}
if (inputStream != null) {
// 创建 XMLMapperBuilder 对象
XMLMapperBuilder xmlParser = new XMLMapperBuilder(inputStream, a(),
xmlResource, con(), ());
// 解析该 XML 文件
xmlPar();
}
}
}
}

在构造函数中,会创建一个MapperBuilderAssistant对象,Mapper 构造器小助手,用于创建XML映射文件中对应相关对象

parse()方法,用于解析Mapper接口:

  1. 获取Mapper接口的名称,例如in,根据Configuration全局配置对象判断该Mapper接口是否被解析过
  1. 没有解析过则调用loadXmlResource()方法解析对应的XML映射文件
  2. 然后解析接口的@CacheNamespace和@CacheNamespaceRef注解,再依次解析方法上面的MyBatis相关注解

注解的相关解析这里就不讲述了,因为我们通常都是使用XML映射文件,逻辑没有特别复杂,都在MapperAnnotationBuilder中进行解析,感兴趣的小伙伴可以看看

1.《如何初始化接口?终于找到答案了MyBatis初始化加载 Mapper 接口与XML文件》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。

2.《如何初始化接口?终于找到答案了MyBatis初始化加载 Mapper 接口与XML文件》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。

3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/gl/2093880.html

上一篇

关于-74中国移动怎么叫74消失,你需要知道这些男子因微信被封跳楼,记者实测:上亿月活的APP,它们的人工客服究竟是不是人

下一篇

关于如何处理偶发的Bug,你需要知道这些常见的电脑蓝屏原因和解决方法

关于如何初始化接口,你需要知道这些无法初始化windows sockets接口

关于如何初始化接口,你需要知道这些无法初始化windows sockets接口

如何初始化接口相关介绍,请试试这个方法。我也有这种情况。现在用这个方法解决了。可能是昨天的自动更新,可能出了问题,可能是单机。但是只要和互联网接触,就不能运行。今天Vista和Win7好像大部分都中奖了。(大卫亚设)。 应该...

如何初始化接口看这里!什么是 COM 接口?

如何初始化接口看这里!什么是 COM 接口?

如何初始化接口相关介绍,如果你懂C#或Java语言,界面将是一个非常熟悉的概念。 接口是一个对象上一组操作的集合,不涉及任何实现的细节,接口标志着方法和实现的分离。计算机中这种现象叫做解耦(decoupled)。 在 C++...

关于如何初始化接口,你需要知道这些Spring Boot如何在启动时初始化资源?实现CommandLineRunner接口

关于如何初始化接口,你需要知道这些Spring Boot如何在启动时初始化资源?实现CommandLineRunner接口

如何初始化接口相关介绍,在实际工作中,项目启动时需要执行初始化任务(如初始化数据库连接、Redis缓存等)的要求。 今天就给大家介绍 CommandLineRunner接口,帮助大家解决项目启动初始化资源操作。 Comman...

关于如何初始化接口,你需要知道这些S7-300集成DP口之间GSD文件方式的DP主从通信(Step7)

关于如何初始化接口,你需要知道这些S7-300集成DP口之间GSD文件方式的DP主从通信(Step7)

如何初始化接口相关介绍,S7-300集成DP端口之间的GSD文件驱动DP主从通信(Step7) PROFIBUS-DP是一种通信标准,一些符合PROFIBUS-DP约定的第三方设备也可以作为SIMATIC master的从属...

如何初始化接口看这里!电脑提示windows通信端口初始化失败的解决方法

如何初始化接口看这里!电脑提示windows通信端口初始化失败的解决方法

如何初始化接口相关介绍,出现Windows系统通信端口初始化失败的消息怎么办?最近,很多用户询问了windows系统通信端口初始化失败的解决方法,我将分享如下。(大卫亚设)。 解决方法: 1、我们把电脑中的360安全卫士退出...