Mybatis 源码解析 -- 基于配置的源码解析(二)
生活随笔
收集整理的這篇文章主要介紹了
Mybatis 源码解析 -- 基于配置的源码解析(二)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
為什么80%的碼農都做不了架構師?>>> ??
mapper解析
接著上篇的配置,本篇主要講解mappers標簽
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration><environments default="dev"><environment id="dev"><transactionManager type="JDBC" /><dataSource type="com.xiaoye.clearworld.datasource.CustomDruidDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql://127.0.0.1:3306/zlgedu" /><property name="username" value="root" /><property name="password" value="root" /></dataSource></environment><environment id="uat"><transactionManager type="JDBC" /><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql://127.0.0.1:3306/zlgedu" /><property name="username" value="root" /><property name="password" value="root" /></dataSource></environment></environments><mappers><mapper class="com.xiaoye.clearworld.persistence.WebsiteZlgeduCompanyMapper"/><!-- 更多………… --></mappers> </configuration>該標簽的主要功能:標記Mybatis數據庫接口或Mybatis映射文件,配置方式有三:
<package name=""/> 數據庫接口所在父包路徑 <mapper class=""/> 數據庫接口類路徑 <mapper resource=""/> 數據庫映射文件路徑 <mapper url=""/> 數據庫映射文件資源路徑源碼解析:org.apache.ibatis.builder.xml.XMLConfigBuilder.parseConfiguration(XNode root)
private void parseConfiguration(XNode root) {try {//issue #117 read properties firstpropertiesElement(root.evalNode("properties"));Properties settings = settingsAsProperties(root.evalNode("settings"));loadCustomVfs(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"));// mappers 標簽解析mapperElement(root.evalNode("mappers"));} catch (Exception e) {throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);}}進入到方法
private void mapperElement(XNode parent) throws Exception {if (parent != null) {for (XNode child : parent.getChildren()) { // 解析 mappers 的子節點if ("package".equals(child.getName())) { // 配置接口掃描包 package 節點(掃描包)String mapperPackage = child.getStringAttribute("name");configuration.addMappers(mapperPackage); // 如果配置了package節點,mybatis默認會將該包下所有的接口類加載到mybatis中} else { // 單獨配置String resource = child.getStringAttribute("resource");String url = child.getStringAttribute("url");String mapperClass = child.getStringAttribute("class");if (resource != null && url == null && mapperClass == null) { // resource xml 文件ErrorContext.instance().resource(resource);InputStream inputStream = Resources.getResourceAsStream(resource);XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());mapperParser.parse();} else if (resource == null && url != null && mapperClass == null) {ErrorContext.instance().resource(url);InputStream inputStream = Resources.getUrlAsStream(url);XMLMapperBuilder 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.");}}}}}得到mappers節點后,解析其子節點。
如果子節點中存在 package 節點,則解析方式如下:
分析上面的代碼:a、根據包名稱轉換得到包路徑;b、根據包路徑獲取該包下所有的文件;c、遍歷文件,取出class結尾的文件;d、判斷是否是指定類或指定類的子類;e:添加并解析
具體的解析(非package節點的解析直接進入這):
public <T> void addMapper(Class<T> type) {if (type.isInterface()) {if (hasMapper(type)) {throw new BindingException("Type " + type + " is already known to the MapperRegistry.");}boolean loadCompleted = false;try {knownMappers.put(type, new MapperProxyFactory<T>(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 parser = new MapperAnnotationBuilder(config, type);parser.parse();loadCompleted = true;} finally {if (!loadCompleted) {knownMappers.remove(type);}}}}分析:1、首先是接口;2、之前未添加過haddMapper;3、存儲:knownMappers.put(type, new MapperProxyFactory<T>(type));4、映射文件解析
映射文件解析
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type); parser.parse(); public MapperAnnotationBuilder(Configuration configuration, Class<?> type) {String resource = type.getName().replace('.', '/') + ".java (best guess)";this.assistant = new MapperBuilderAssistant(configuration, resource);this.configuration = configuration;this.type = type;sqlAnnotationTypes.add(Select.class);sqlAnnotationTypes.add(Insert.class);sqlAnnotationTypes.add(Update.class);sqlAnnotationTypes.add(Delete.class);sqlProviderAnnotationTypes.add(SelectProvider.class);sqlProviderAnnotationTypes.add(InsertProvider.class);sqlProviderAnnotationTypes.add(UpdateProvider.class);sqlProviderAnnotationTypes.add(DeleteProvider.class);} public void parse() {String resource = type.toString();if (!configuration.isResourceLoaded(resource)) { // 判斷是否解析過loadXmlResource(); // 解析映射文件configuration.addLoadedResource(resource); // 添加已解析assistant.setCurrentNamespace(type.getName()); // 校驗映射文件命名空間parseCache(); // 緩存解析parseCacheRef(); // TODOMethod[] methods = type.getMethods(); // 獲取接口的所有方法for (Method method : methods) { // 遍歷try {// issue #237if (!method.isBridge()) { // parseStatement(method); // }} catch (IncompleteElementException e) {configuration.addIncompleteMethod(new MethodResolver(this, method));}}}parsePendingMethods(); //}映射文件解析:loadXmlResource();
?
轉載于:https://my.oschina.net/asddsa/blog/1573374
總結
以上是生活随笔為你收集整理的Mybatis 源码解析 -- 基于配置的源码解析(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js计算字数
- 下一篇: 说一个人是边角料什么意思