MyBatis是如何初始化的
本文分享自华为云社区《MyBatis详解初始化基本过程云社区华为云》,作者:龙哥手记。MyBatis初始化的方式及引入
MyBatis的初始化可以有两种方式:基于XML配置文件:基于XML配置文件的方式是将MyBatis的所有配置信息放在XML文件中,MyBatis通过加载并XML配置文件,将配置文信息组装成内部的Configuration对象。基于JavaAPI:这种方式不使用XML配置文件,需要MyBatis使用者在Java代码中,手动创建Configuration对象,然后将配置参数set进入Configuration对象中。初始化方式XML配置
接下来我们将通过基于XML配置文件方式的MyBatis初始化,深入探讨MyBatis是如何通过配置文件构建Configuration对象,并使用它。
现在就从使用MyBatis的简单例子入手,深入分析一下MyBatis是怎样完成初始化的,都初始化了什么。看以下代码:mybatis初始化Stringresourcemybatisconfig。xml;InputStreaminputStreamResources。getResourceAsStream(resource);SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder()。build(inputStream);创建SqlSessionSqlSessionsqlSessionsqlSessionFactory。openSession();执行SQL语句ListlistsqlSession。selectList(com。foo。bean。BlogMapper。queryAllBlogInfo);
有过MyBatis使用经验的读者会知道,上述语句的作用是执行com。foo。bean。BlogMapper。queryAllBlogInfo定义的SQL语句,返回一个List结果集。总的来说,上述代码经历了三个阶段(本系列也对应三篇文章分别讲解):mybatis初始化本文创建SqlSession详解后文执行SQL语句详解后文
上述代码的功能是根据配置文件mybatisconfig。xml配置文件,创建SqlSessionFactory对象,然后产生SqlSession,执行SQL语句。而mybatis的初始化就发生在第三句:SqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder()。build(inputStream);现在就让我们看看第三句到底发生了什么。MyBatis初始化基本过程:
SqlSessionFactoryBuilder根据传入的数据流生成Configuration对象,然后根据Configuration对象创建默认的SqlSessionFactory实例。
初始化的基本过程如下序列图所示:
由上图所示,mybatis初始化要经过简单的以下几步:调用SqlSessionFactoryBuilder对象的build(inputStream)方法;SqlSessionFactoryBuilder会根据输入流inputStream等信息创建XMLConfigBuilder对象;SqlSessionFactoryBuilder调用XMLConfigBuilder对象的parse()方法;XMLConfigBuilder对象返回Configuration对象;SqlSessionFactoryBuilder根据Configuration对象创建一个DefaultSessionFactory对象;SqlSessionFactoryBuilder返回DefaultSessionFactory对象给Client,供Client使用。
SqlSessionFactoryBuilder相关的代码如下所示:publicSqlSessionFactorybuild(InputStreaminputStream){returnbuild(inputStream,null,null);}publicSqlSessionFactorybuild(InputStreaminputStream,Stringenvironment,Propertiesproperties){try{2。创建XMLConfigBuilder对象用来解析XML配置文件,生成Configuration对象XMLConfigBuilderparsernewXMLConfigBuilder(inputStream,environment,properties);3。将XML配置文件内的信息解析成Java对象Configuration对象Configurationconfigparser。parse();4。根据Configuration对象创建出SqlSessionFactory对象returnbuild(config);}catch(Exceptione){throwExceptionFactory。wrapException(ErrorbuildingSqlSession。,e);}finally{ErrorContext。instance()。reset();try{inputStream。close();}catch(IOExceptione){Intentionallyignore。Preferpreviouserror。}}}从此处可以看出,MyBatis内部通过Configuration对象来创建SqlSessionFactory,用户也可以自己通过API构造好Configuration对象,调用此方法创SqlSessionFactorypublicSqlSessionFactorybuild(Configurationconfig){returnnewDefaultSqlSessionFactory(config);}
上述的初始化过程中,涉及到了以下几个对象:SqlSessionFactoryBuilder:SqlSessionFactory的构造器,用于创建SqlSessionFactory,采用了Builder设计模式Configuration:该对象是mybatisconfig。xml文件中所有mybatis配置信息SqlSessionFactory:SqlSession工厂类,以工厂形式创建SqlSession对象,采用了Factory工厂设计模式XmlConfigParser:负责将mybatisconfig。xml配置文件解析成Configuration对象,共SqlSessonFactoryBuilder使用,创建SqlSessionFactory创建Configuration对象的过程
接着上述的MyBatis初始化基本过程讨论,当SqlSessionFactoryBuilder执行build()方法,调用了XMLConfigBuilder的parse()方法,然后返回了Configuration对象。那么parse()方法是如何处理XML文件,生成Configuration对象的呢?XMLConfigBuilder会将XML配置文件的信息转换为Document对象
而XML配置定义文件DTD转换成XMLMapperEntityResolver对象,然后将二者封装到XpathParser对象中,XpathParser的作用是提供根据Xpath表达式获取基本的DOM节点Node信息的操作。如下图所示:
之后XMLConfigBuilder调用parse()方法
会从XPathParser中取出节点对应的Node对象,然后解析此Node节点的子Node:properties,settings,typeAliases,typeHandlers,objectFactory,objectWrapperFactory,plugins,environments,databaseIdProvider,mappers:publicConfigurationparse(){if(parsed){thrownewBuilderException(EachXMLConfigBuildercanonlybeusedonce。);}parsedtrue;源码中没有这一句,只有parseConfiguration(parser。evalNode(configuration));为了让读者看得更明晰,源码拆分为以下两句XNodeconfigurationNodeparser。evalNode(configuration);parseConfiguration(configurationNode);returnconfiguration;}解析configuration节点下的子节点信息,然后将解析的结果设置到Configuration对象中privatevoidparseConfiguration(XNoderoot){try{1。首先处理properties节点propertiesElement(root。evalNode(properties));issue117readpropertiesfirst2。处理typeAliasestypeAliasesElement(root。evalNode(typeAliases));3。处理插件pluginElement(root。evalNode(plugins));4。处理objectFactoryobjectFactoryElement(root。evalNode(objectFactory));5。objectWrapperFactoryobjectWrapperFactoryElement(root。evalNode(objectWrapperFactory));6。settingssettingsElement(root。evalNode(settings));7。处理environmentsenvironmentsElement(root。evalNode(environments));readitafterobjectFactoryandobjectWrapperFactoryissue6318。databasedatabaseIdProviderElement(root。evalNode(databaseIdProvider));9。typeHandlerstypeHandlerElement(root。evalNode(typeHandlers));10。mappersmapperElement(root。evalNode(mappers));}catch(Exceptione){thrownewBuilderException(ErrorparsingSQLMapperConfiguration。Cause:e,e);}}
注意:在上述代码中,还有一个非常重要的地方,就是解析XML配置文件子节点的方法mapperElements(root。evalNode(mappers)),它将解析我们配置的Mapper。xml配置文件,Mapper配置文件可以说是MyBatis的核心,MyBatis的特性和理念都体现在此Mapper的配置和设计上。然后将这些值解析出来设置到Configuration对象中
解析子节点的过程这里就不一一介绍了,用户可以参照MyBatis源码仔细揣摩,我们就看上述的environmentsElement(root。evalNode(environments));方法是如何将environments的信息解析出来,设置到Configuration对象中的:解析environments节点,并将结果设置到Configuration对象中注意:创建envronment时,如果SqlSessionFactoryBuilder指定了特定的环境(即数据源);则返回指定环境(数据源)的Environment对象,否则返回默认的Environment对象;这种方式实现了MyBatis可以连接多数据源privatevoidenvironmentsElement(XNodecontext)throwsException{if(context!null){if(environmentnull){environmentcontext。getStringAttribute(default);}for(XNodechild:context。getChildren()){Stringidchild。getStringAttribute(id);if(isSpecifiedEnvironment(id)){1。创建事务工厂TransactionFactoryTransactionFactorytxFactorytransactionManagerElement(child。evalNode(transactionManager));DataSourceFactorydsFactorydataSourceElement(child。evalNode(dataSource));2。创建数据源DataSourceDataSourcedataSourcedsFactory。getDataSource();3。构造Environment对象Environment。BuilderenvironmentBuildernewEnvironment。Builder(id)。transactionFactory(txFactory)。dataSource(dataSource);4。将创建的Envronment对象设置到configuration对象中configuration。setEnvironment(environmentBuilder。build());}}}}privatebooleanisSpecifiedEnvironment(Stringid){if(environmentnull){thrownewBuilderException(Noenvironmentspecified。);}elseif(idnull){thrownewBuilderException(Environmentrequiresanidattribute。);}elseif(environment。equals(id)){returntrue;}returnfalse;}返回Configuration对象
将上述的MyBatis初始化基本过程的序列图细化:
初始化方式基于JavaAPI
当然我们可以使用XMLConfigBuilder手动解析XML配置文件来创建Configuration对象,代码如下:Stringresourcemybatisconfig。xml;InputStreaminputStreamResources。getResourceAsStream(resource);手动创建XMLConfigBuilder,并解析创建Configuration对象XMLConfigBuilderparsernewXMLConfigBuilder(inputStream,null,null);看这里Configurationconfigurationparser。parse();使用Configuration对象创建SqlSessionFactorySqlSessionFactorysqlSessionFactorynewSqlSessionFactoryBuilder()。build(configuration);使用MyBatisSqlSessionsqlSessionsqlSessionFactory。openSession();ListlistsqlSession。selectList(com。foo。bean。BlogMapper。queryAllBlogInfo);
点击下方,第一时间了解华为云新鲜技术
华为云博客大数据博客AI博客云计算博客开发者中心华为云
肉馅鲜嫩多汁有技巧,调馅时多放2样,油润鲜香还不腥,一口爆汁肉馅鲜嫩多汁有技巧,调馅时多放2样,油润鲜香还不腥,一口爆汁肉馅,在生活中太常见、太常用了,不管是包饺子、包馄饨,还是包大包子,又或者是做肉丸子等等,都离不开一道好吃的肉……
皮蛋直接凉拌,难怪吃着又腥又涩,多做1步,皮蛋鲜香又嫩滑皮蛋直接凉拌,难怪吃着又腥又涩,多做1步,皮蛋鲜香又嫩滑皮蛋在夏天可是很受欢迎的,感觉酷热难耐的时候,来一盘凉拌皮蛋端上桌,对于喜欢吃的人来讲,简直是人间美味。吃一口鲜香……
奶茶报告出炉这10个地方的人最爱喝奶茶,看你在不在其中?1987年,第一杯珍珠奶茶诞生。在经历了2。0时代的冲泡式奶茶、3。0时代的果饮奶盖饮品潮流后,新式茶饮4。0时代,奶茶消费有了减糖、粥化的新趋势。5月全民营养周期间,人……
修理铁路的高达,将取代人工进行铁路修理就在前不久西日本铁道株式会社在推特上发布了人形巨型机器人的相关视频,在这个视频中操作员在VR技术的帮助下对铁路展开了维修与处理。在视频中这款铁路维修机器人被安装在了个液压……
高质量文案1。人在低谷不谈格局生存才是王道,身处逆境不谈情怀务实才是根本2。社交之所以累,是因为都在拐弯抹角的炫耀自己,添油加醋的贬低别人,相互窥探搬弄是非!3。不要在垃圾堆……
CBA三消息吉林超外61分三双,西热力江被打服,北控欲签雅尼大家好呀,我是北柠,各位小伙伴们要养成先看后赞的习惯哦!吉林队这个赛季依旧只有一名外援琼斯可以使用,但是琼斯的能力可非同一般,他一个人可以抵上其他球队的两名外援了,而且琼……
6种酱汁配方馋嘴酱:泡老姜三包,泡萝卜三桶,花椒一斤,鸡油二斤,菜籽油8斤,醪糟一瓶,泡子姜三桶,黄绿灯笼椒三桶,麻椒一斤,牛油4斤,野山椒三袋,二锅头一瓶,洋葱蒜蓉各0。5斤(泡老姜,泡……
综述中国市场机遇是企业不能错过的巨大商机欧洲企业欢迎中国省市新华社法兰克福12月28日电综述:中国市场机遇是企业不能错过的巨大商机欧洲企业欢迎中国省市商务代表团访欧新华社记者单玮怡12月以来,中国多个省市组织政府商贸骨干、企……
吃丨北京丨目前觉得京城性价比最高的自助餐前几个月和妈妈在北京吃了几家自助,实话是,泉州吃自助还是划算,价钱差不多,能吃到的好料可不少直到去了这家餐厅,嗯!可以啊!不算太贵,吃到不少好吃的东西。算是性价比很高的一……
炒芹菜时,直接炒是大错特错!若少了这1步,芹菜不香还不入味!给大家介绍一道素菜:西芹炒豆干。众所周知,芹菜价格便宜,营养丰富,是很普通的保健蔬菜;是早些年从国外引进的品种,叶柄宽厚,和旱菜(香芹)具有相同的营养和食疗价值,它有平肝降压,……
你知道酱油分烹调和凉拌两种用途吗?家里做饭菜最常用的一种调味料就是酱油,尤其是过年过节的时候,用量就更多了。但是你知道吗?酱油有加热烹调和凉拌(点、蘸等)两种用途,但很多人在购买时都不太注意选择,家里往往只备有……
白象方便面最好不要成为第二个鸿星尔克文章来自微信公众号:记忆承载。欢迎关注阅读全文。老坛酸菜的梗,大家都知道。315曝光脚踩酸菜不卫生这件事几乎把涉及的方便面都拉下了水。其实这事儿怎么说呢,肯德基里面……