mybatis源码-解析配置文件(三)之配置文件Configuration解析(超详细, 值得收藏) (6)

MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。在后续的 XXXXmapper.xml 文件中, 可以指定 databaseId

3.3.9.4 解析过程 private void databaseIdProviderElement(XNode context) throws Exception { DatabaseIdProvider databaseIdProvider = null; if (context != null) { String type = context.getStringAttribute("type"); // awful patch to keep backward compatibility // 为了兼容, 更改 type 为 VENDOR 至 DB_VENDOR if ("VENDOR".equals(type)) { type = "DB_VENDOR"; } // 解析对应的配置信息 Properties properties = context.getChildrenAsProperties(); // 通过反射生成对象 databaseIdProvider = (DatabaseIdProvider) resolveClass(type).newInstance(); // 设置属性 databaseIdProvider.setProperties(properties); } Environment environment = configuration.getEnvironment(); if (environment != null && databaseIdProvider != null) { String databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource()); configuration.setDatabaseId(databaseId); } } 3.3.10 typeHandlers 相关属性 3.3.10.1 成员变量 protected final TypeHandlerRegistry typeHandlerRegistry; 3.3.10.2 对应 XML 节点:<typeHandlers> <typeHandlers> <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/> </typeHandlers> 3.3.10.3 作用

无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。

3.3.10.4 解析过程 private void typeHandlerElement(XNode parent) throws Exception { if (parent != null) { // 遍历所有的子节点 for (XNode child : parent.getChildren()) { // 包(package)子节点 if ("package".equals(child.getName())) { String typeHandlerPackage = child.getStringAttribute("name"); typeHandlerRegistry.register(typeHandlerPackage); } else { // 非 package 子节点 // 获取相应的属性 String javaTypeName = child.getStringAttribute("javaType"); String jdbcTypeName = child.getStringAttribute("jdbcType"); String handlerTypeName = child.getStringAttribute("handler"); // 根据属性, 通过反射创建对象 Class<?> javaTypeClass = resolveClass(javaTypeName); JdbcType jdbcType = resolveJdbcType(jdbcTypeName); Class<?> typeHandlerClass = resolveClass(handlerTypeName); // 将对象注册到 typeHandlerRegistry 对象中 if (javaTypeClass != null) { if (jdbcType == null) { typeHandlerRegistry.register(javaTypeClass, typeHandlerClass); } else { typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass); } } else { typeHandlerRegistry.register(typeHandlerClass); } } } } } 3.3.11 mappers 相关属性 3.3.11.1 成员变量 //映射的语句 protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection"); // 缓存集合 protected final Map<String, Cache> caches = new StrictMap<Cache>("Caches collection"); // 结果集合 protected final Map<String, ResultMap> resultMaps = new StrictMap<ResultMap>("Result Maps collection"); // 存储过程参数集合 protected final Map<String, ParameterMap> parameterMaps = new StrictMap<ParameterMap>("Parameter Maps collection"); // 主键生成器合集 protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<KeyGenerator>("Key Generators collection"); protected final Set<String> loadedResources = new HashSet<String>(); protected final Map<String, XNode> sqlFragments = new StrictMap<XNode>("XML fragments parsed from previous mappers"); // 存储不完整的语句 protected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<XMLStatementBuilder>(); protected final Collection<CacheRefResolver> incompleteCacheRefs = new LinkedList<CacheRefResolver>(); protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<ResultMapResolver>(); protected final Collection<MethodResolver> incompleteMethods = new LinkedList<MethodResolver>(); 3.3.11.2 对应 XML 节点:<mappers> <mappers> <package/> </mappers> 3.3.11.3 作用

mybatis-config.xml 配置文件中的<mappers>节点会告诉 MyBatis 去哪些位置查找映射配置文件以及使用了配置注解标识的接口。

这也是配置文件解析的重点, 后续会开一篇文章进行讲解。

3.3.11.4 解析过程 private void mapperElement(XNode parent) throws Exception { if (parent != null) { for (XNode child : parent.getChildren()) { // <package> 子节点, 就是包下面的类 if ("package".equals(child.getName())) { String mapperPackage = child.getStringAttribute("name"); configuration.addMappers(mapperPackage); } else { // 对应 <mapper> 子节点 // resource / url / class 中 3选1 String resource = child.getStringAttribute("resource"); String url = child.getStringAttribute("url"); String mapperClass = child.getStringAttribute("class"); // 如果节点指定了 resource 或 url, 则创建 XMLMapperBuilder 对象, // 通过该对象的 parse() 函数将 mapper 添加到 configuration 中 if (resource != null && url == null && mapperClass == null) { 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."); } } } } }

这个是后面需要更详细的开章节进行讲解的。

结语

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdsxy.html