后端技术:Mybatis是如何解析配置文件的?
關注“Java后端技術全棧”
回復“面試”獲取全套面試資料
在以前文章中,我們把Mybatis源碼閱讀的整個流程梳理了一遍。今天,我們來詳細聊聊,Mybatis是如何解析配置文件的。
這是今天分析的流程圖:
還是從案例開始。
demo案例
???public?static?void?main(String[]?args)?{String?resource?=?"mybatis-config.xml";InputStream?inputStream?=?null;SqlSession?sqlSession?=?null;try?{inputStream?=?Resources.getResourceAsStream(resource);SqlSessionFactory?sqlSessionFactory?=?new?SqlSessionFactoryBuilder().build(inputStream);sqlSession?=?sqlSessionFactory.openSession();UserMapper?userMapper?=?sqlSession.getMapper(UserMapper.class);System.out.println(userMapper.selectById(1));}?catch?(Exception?e)?{e.printStackTrace();}?finally?{try?{inputStream.close();}?catch?(IOException?e)?{e.printStackTrace();}sqlSession.close();}}見證奇跡
從SqlSessionFactoryBuilder開始。
SqlSessionFactoryBuilder類
org.apache.ibatis.session.SqlSessionFactoryBuilder該類里全是build方法各種重載。
//這個方法啥也沒干?? public?SqlSessionFactory?build(InputStream?inputStream)?{return?build(inputStream,?null,?null);}
最終來到另外一個build方法里:
??public?SqlSessionFactory?build(InputStream?inputStream,?String?environment,?Properties?properties)?{try?{//創建一個XMLConfigBuilder對象??XMLConfigBuilder?parser?=?new?XMLConfigBuilder(inputStream,?environment,?properties);return?build(parser.parse());}?catch?(Exception?e)?{throw?ExceptionFactory.wrapException("Error?building?SqlSession.",?e);}?finally?{ErrorContext.instance().reset();try?{inputStream.close();}?catch?(IOException?e)?{//?Intentionally?ignore.?Prefer?previous?error.}}}XMLConfigBuilder類
該類的構造方法重載:
首先進入:
public?XMLConfigBuilder(InputStream?inputStream,?String?environment,?Properties?props)?{this(new?XPathParser(inputStream,?true,?props,?new?XMLMapperEntityResolver()),?environment,?????props); } private?XMLConfigBuilder(XPathParser?parser,?String?environment,?Properties?props)?{super(new?Configuration());ErrorContext.instance().resource("SQL?Mapper?Configuration");this.configuration.setVariables(props);this.parsed?=?false;this.environment?=?environment;this.parser?=?parser; }build(parser.parse());中的parser.parse();
mybatis-config.xml在哪里解析的呢?
請看下面這個方法:
//該方法返回一個Configuration對象 public?Configuration?parse()?{if?(parsed)?{throw?new?BuilderException("Each?XMLConfigBuilder?can?only?be?used?once.");}parsed?=?true;//關鍵點parseConfiguration(parser.evalNode("/configuration"));return?configuration; }parseConfiguration(parser.evalNode("/configuration"));
終于看到開始解析配置文件了:
進入方法parseConfiguration。
??private?void?parseConfiguration(XNode?root)?{try?{//issue?#117?read?properties?firstpropertiesElement(root.evalNode("properties"));Properties?settings?=?settingsAsProperties(root.evalNode("settings"));loadCustomVfs(settings);loadCustomLogImpl(settings);typeAliasesElement(root.evalNode("typeAliases"));pluginElement(root.evalNode("plugins"));objectFactoryElement(root.evalNode("objectFactory"));objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));reflectorFactoryElement(root.evalNode("reflectorFactory"));settingsElement(settings);//?read?it?after?objectFactory?and?objectWrapperFactory?issue?#631environmentsElement(root.evalNode("environments"));databaseIdProviderElement(root.evalNode("databaseIdProvider"));typeHandlerElement(root.evalNode("typeHandlers"));mapperElement(root.evalNode("mappers"));}?catch?(Exception?e)?{throw?new?BuilderException("Error?parsing?SQL?Mapper?Configuration.?Cause:?"?+?e,?e);}}這里就是把mybatis-config.xml內容解析,然后設置到Configuration對象中。
那么我們定義的Mapper.xml是在哪里解析的呢?
我們的Mapper.xml在mybatis-config.xml中的配置是這樣的:
<mapper>使用方式有以下四種:
//1使用類路徑 <mappers><mapper?resource="org/mybatis/builder/AuthorMapper.xml"/><mapper?resource="org/mybatis/builder/BlogMapper.xml"/><mapper?resource="org/mybatis/builder/PostMapper.xml"/> </mappers> //2使用絕對url路徑 <mappers><mapper?url="file:///var/mappers/AuthorMapper.xml"/><mapper?url="file:///var/mappers/BlogMapper.xml"/><mapper?url="file:///var/mappers/PostMapper.xml"/> </mappers> //3使用java類名 <mappers><mapper?class="org.mybatis.builder.AuthorMapper"/><mapper?class="org.mybatis.builder.BlogMapper"/><mapper?class="org.mybatis.builder.PostMapper"/> </mappers>//4自動掃描包下所有映射器 <mappers><package?name="org.mybatis.builder"/> </mappers>繼續源碼分析,我們在上面mybatis-config.xml解析中可以看到:
我們不妨進入這個方法看看:
?private?void?mapperElement(XNode?parent)?throws?Exception?{if?(parent?!=?null)?{for?(XNode?child?:?parent.getChildren())?{//自動掃描包下所有映射器if?("package".equals(child.getName()))?{String?mapperPackage?=?child.getStringAttribute("name");//放??configuration.addMappers(mapperPackage);}?else?{String?resource?=?child.getStringAttribute("resource");String?url?=?child.getStringAttribute("url");String?mapperClass?=?child.getStringAttribute("class");//使用java類名if?(resource?!=?null?&&?url?==?null?&&?mapperClass?==?null)?{ErrorContext.instance().resource(resource);//根據文件存放目錄,讀取XxxMapper.xmlInputStream?inputStream?=?Resources.getResourceAsStream(resource);//映射器比較復雜,調用XMLMapperBuilder//注意在for循環里每個mapper都重新new一個XMLMapperBuilder,來解析XMLMapperBuilder?mapperParser?=?new?XMLMapperBuilder(inputStream,?configuration,?resource,?configuration.getSqlFragments());mapperParser.parse();//使用絕對url路徑}?else?if?(resource?==?null?&&?url?!=?null?&&?mapperClass?==?null)?{ErrorContext.instance().resource(url);InputStream?inputStream?=?Resources.getUrlAsStream(url);//映射器比較復雜,調用XMLMapperBuilderXMLMapperBuilder?mapperParser?=?new?XMLMapperBuilder(inputStream,?configuration,?url,?configuration.getSqlFragments());mapperParser.parse();//使用類路徑????}?else?if?(resource?==?null?&&?url?==?null?&&?mapperClass?!=?null)?{Class<?>?mapperInterface?=?Resources.classForName(mapperClass);//直接把這個映射加入配置configuration.addMapper(mapperInterface);}?else?{throw?new?BuilderException("A?mapper?element?may?only?specify?a?url,?resource?or?class,?but?not?more?than?one.");}}}}}這里剛剛和我們的上面說的<mapper>使用的方式完全是一模一樣的。
到這里,配置文件mybatis-config.xml和我們定義映射文件XxxMapper.xml就全部解析完成。
回到SqlSessionFactoryBuilder類
前面講到了XMLConfigBuilder中的parse方法,并返回了一個Configuration對象。
build(parser.parse());
這個build方法就是傳入一個Configuration對象,然后構建一個DefaultSqlSession對象。
??public?SqlSessionFactory?build(Configuration?config)?{return?new?DefaultSqlSessionFactory(config);}繼續回到我們的demo代碼中這一行代碼里:
SqlSessionFactory?sqlSessionFactory?=?new?SqlSessionFactoryBuilder().build(inputStream);這一行代碼就相當于:
SqlSessionFactory?sqlSessionFactory?=?new?new?DefaultSqlSessionFactory();到這里,我們的整個流程就搞定了。
IT技術分享社區
個人博客網站:https://programmerblog.xyz
文章推薦程序員效率:畫流程圖常用的工具程序員效率:整理常用的在線筆記軟件遠程辦公:常用的遠程協助軟件,你都知道嗎?51單片機程序下載、ISP及串口基礎知識硬件:斷路器、接觸器、繼電器基礎知識
總結
以上是生活随笔為你收集整理的后端技术:Mybatis是如何解析配置文件的?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java视频在线观看网址
- 下一篇: 逃跑吧少年服务器临时维护中,逃跑吧少年—