前言:
眼前看官们对“java分析文件”都比较讲究,咱们都需要剖析一些“java分析文件”的相关知识。那么小编也在网上网罗了一些有关“java分析文件””的相关内容,希望小伙伴们能喜欢,大家快快来了解一下吧!xml文件解析的本质
mybatis中有两类xml文件需要解析,一类是mybatis配置文件,另一类是mybatis的mapper文件。
解析的本质就是将配置文件中的数据信息,解析存储到java对象当中,然后加载到内存使用。
mybatis配置文件的解析
XMLConfigBuilder.java 是用来解析mybatis配置文件的。
解析配置文件是由 SqlSessionFactoryBuilder创建时,调用build构建SqlSessionFactoryBuilder对象时,调用XMLConfigBuilder实现解析。
XMLConfigBuilder中解析配置文件的主要方法
java中方法解析配置文件
public Configuration parse() { if (parsed) { throw new BuilderException("Each XMLConfigBuilder can only be used once."); } parsed = true; parseConfiguration(parser.evalNode("/configuration")); return configuration; } private void parseConfiguration(XNode root) { try { // issue #117 read properties first propertiesElement(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 #631 environmentsElement(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配置文件
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" ";><configuration> <!-- 1、属性:例如jdbc.properties --> <properties resource="jdbc.properties"></properties> <!-- 2、设置:定义全局性设置,例如开启二级缓存 --> <settings> <setting name="cacheEnabled" value="true"/> </settings> <!-- 3、类型名称:为一些类定义别名 --> <typeAliases> <typeAlias type="com.panshenlian.pojo.User" alias="user"></typeAlias> </typeAliases> <!-- 4、类型处理器:定义Java类型与数据库中的数据类型之间的转换关系 --> <typeHandlers></typeHandlers> <!-- 5、对象工厂 --> <objectFactory type=""></objectFactory> <!-- 6、插件:mybatis的插件,支持自定义插件 --> <plugins> <plugin interceptor=""></plugin> </plugins> <!-- 7、环境:配置mybatis的环境 --> <environments default="development"> <!-- 环境变量:支持多套环境变量,例如开发环境、生产环境 --> <environment id="development"> <!-- 事务管理器:默认JDBC --> <transactionManager type="JDBC" /> <!-- 数据源:使用连接池,并加载mysql驱动连接数据库 --> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /> <property name="username" value="root" /> <property name="password" value="123456" /> </dataSource> </environment> </environments> <!-- 8、数据库厂商标识 --> <databaseIdProvider type=""></databaseIdProvider> <!-- 9、映射器:指定映射文件或者映射类 --> <mappers> <mapper resource="UserMapper.xml" /> </mappers> </configuration>
注意:Mybatis配置文件的属性位置顺序是 固定 的,不允许 颠倒顺序,否则 Mybatis 解析 XML 文件的时候就会抛出异常。
mybatis Mapper文件的解析
XMLConfigBuilder解析mybatis配置文件,最后一个标签就是 mappers 。
//mybatis配置文件的解析mapperElement(root.evalNode("mappers"));
代码中的标签就是对应于 映射器(mappers) 中的标签。
java中mappers标签
映射器(mappers)
既然 MyBatis 的行为已经由上述元素配置完了,我们现在就要来定义 SQL 映射语句了。 但首先,我们需要告诉 MyBatis 到哪里去找到这些语句。 在自动查找资源方面,Java 并没有提供一个很好的解决方案,所以最好的办法是直接告诉 MyBatis 到哪里去找映射文件。 你可以使用相对于类路径的资源引用,或完全限定资源定位符(包括 形式的 URL),或类名和包名等。例如:
<!-- 使用相对于类路径的资源引用 --><mappers> <mapper resource="org/mybatis/builder/AuthorMapper.xml"/> <mapper resource="org/mybatis/builder/BlogMapper.xml"/> <mapper resource="org/mybatis/builder/PostMapper.xml"/></mappers>
<!-- 使用完全限定资源定位符(URL) --><mappers> <mapper url=";/> <mapper url=";/> <mapper url=";/></mappers>
<!-- 使用映射器接口实现类的完全限定类名 --><mappers> <mapper class="org.mybatis.builder.AuthorMapper"/> <mapper class="org.mybatis.builder.BlogMapper"/> <mapper class="org.mybatis.builder.PostMapper"/></mappers>
<!-- 将包内的映射器接口实现全部注册为映射器 --><mappers> <package name="org.mybatis.builder"/></mappers>
注意 :
扫描接口或者扫描xml文件。如果是扫描的是接口,那么xml和接口要在同一目录下或者指定xml文件所在目录。如果扫描的是xml文件,就不需要扫描接口。
扫描接口为啥需要再次扫描xml文件:使用mapper接口,无法得知xml文件在哪。
扫描xml文件为啥不需要扫描接口:xml文件中的 namespace就是mapper接口 全限定名。
XMLMapperBuilder 解析mapper xml文件的核心
解析mapper 代码
public void parse() { // 判断资源是否重复加载 //进入判断 是 首次加载 if (!configuration.isResourceLoaded(resource)) { //解析 mapper xml 文件 configurationElement(parser.evalNode("/mapper")); //添加资源到配置对象中 用于检测是否 首次加载 configuration.addLoadedResource(resource); bindMapperForNamespace(); } parsePendingResultMaps(); parsePendingCacheRefs(); parsePendingStatements(); }
解析mapper 文件内容的代码
private void configurationElement(XNode context) { try { String namespace = context.getStringAttribute("namespace"); if (namespace == null || namespace.isEmpty()) { throw new BuilderException("Mapper's namespace cannot be empty"); } builderAssistant.setCurrentNamespace(namespace); cacheRefElement(context.evalNode("cache-ref")); cacheElement(context.evalNode("cache")); parameterMapElement(context.evalNodes("/mapper/parameterMap")); // java 对象属性 与 数据库字段 对照关系 resultMapElements(context.evalNodes("/mapper/resultMap")); sqlElement(context.evalNodes("/mapper/sql")); // xml 文件编写的SQL语句 buildStatementFromContext(context.evalNodes("select|insert|update|delete")); } catch (Exception e) { throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e); } }
小结:
SqlSessionFactoryBuilder创建时,创建了XMLConfigBuilder对象,同时XMLConfigBuilder又创建了XMLMapperBuilder对象。调用两个builder对象完成mybatis中xml的解析,至于细节处调用的对象就不复述了。
问题来了,创建的对象最后去哪里了那?
创建SqlSessionFactoryBuilder 使用 build()方法,返回的是SqlSessionFactory对象,但是生成SqlSessionFactory对象时需要,一个入参Configuration对象。
根据上面的代码往下跟踪,得到 XMLConfigBuilder 对象 最后 使用 super(new Configuration()) 生成的Configuration对象。
parseConfiguration方法中,所有解析后的xml数据都是存放在Configuration对象当中。
小结:
Configuration对象存储了,所有的xml解析后的数据。
标签: #java分析文件