Mybatis源码第2天 -- 加载配置。

电玩女神 2022-05-22 02:06 250阅读 0赞

上篇说到,SqlSession,SqlSession怎么来的?是SqlSessionFactoryBuilder构建出来的。在构建的时候,加载了Mybatis的配置文件。

  1. public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
  2. try {
  3. XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
  4. return build(parser.parse());
  5. } catch (Exception e) {
  6. throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  7. } finally {
  8. ErrorContext.instance().reset();
  9. try {
  10. reader.close();
  11. } catch (IOException e) {
  12. // Intentionally ignore. Prefer previous error.
  13. }
  14. }
  15. }build(parser.parse());
  16. } catch (Exception e) {
  17. throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  18. } finally {
  19. ErrorContext.instance().reset();
  20. try {
  21. reader.close();
  22. } catch (IOException e) {
  23. // Intentionally ignore. Prefer previous error.
  24. }
  25. }
  26. }

还有一处相似的地方,见SqlSessionFactoryBuilder.java.

看build(parse.parse())处。这个parser.parser();就是在加载mybatis-config.xml,和Mapper配置文件。

今天来说一说,加载配置文件。

Mybatis的主要配置文件有两个,mybatis-config.xml和Mapper配置文件。当然还有注解配置的方式。

对于两个xml配置文件。Mybatis提供了两个类来加载。分别是XmlConfigBuilder(加载Mybatis-config.xml)和XmlMapperBuilder(加载Mapper配置文件).

首先看一下parse()这个方法吧。

  1. /**
  2. * 解析mybatis-config.xml
  3. * @return
  4. */
  5. public Configuration parse() {
  6. // 如果已经解析过就抛出异常。
  7. if (parsed) {
  8. throw new BuilderException("Each XMLConfigBuilder can only be used once.");
  9. }
  10. parsed = true;
  11. // 正式解析mybatis-config.xml,从configuration根节点开始。
  12. parseConfiguration(parser.evalNode("/configuration"));
  13. return configuration;
  14. }

接下来就是具体的加载各项配置

  1. // 具体加配置
  2. private void parseConfiguration(XNode root) {
  3. try {
  4. // 加载properties节点
  5. propertiesElement(root.evalNode("properties"));
  6. // 加载settings节点。
  7. Properties settings = settingsAsProperties(root.evalNode("settings"));
  8. loadCustomVfs(settings);
  9. // 加载别名。
  10. typeAliasesElement(root.evalNode("typeAliases"));
  11. // 加载插件
  12. pluginElement(root.evalNode("plugins"));
  13. // 加载objectFactory
  14. objectFactoryElement(root.evalNode("objectFactory"));
  15. // 加载ObjectWrapperFactoryElement
  16. objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
  17. // 加载reflectorFactory
  18. reflectorFactoryElement(root.evalNode("reflectorFactory"));
  19. settingsElement(settings);
  20. // read it after objectFactory and objectWrapperFactory issue #631
  21. environmentsElement(root.evalNode("environments"));
  22. // 加载databaseIdProvider
  23. databaseIdProviderElement(root.evalNode("databaseIdProvider"));
  24. // 加载typeHandlers
  25. typeHandlerElement(root.evalNode("typeHandlers"));
  26. //加载mapper配置文件。
  27. mapperElement(root.evalNode("mappers"));
  28. } catch (Exception e) {
  29. throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
  30. }
  31. }

这么看起来有些空洞,,,,为什么药解析这些元素啊?

我还是从网上百度一个比较完成mybatis-config.xml文件吧。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  3. "http://mybatis.org/dtd/mybatis-3-config.dtd">
  4. <configuration>
  5. <!--properties-->
  6. <properties resource="org/mybatis/example/config.properties">
  7. <property name="username" value="dev_user"/>
  8. <property name="password" value="F2Fa3!33TYyg"/>
  9. </properties>
  10. <!--settings-->
  11. <settings>
  12. <setting name="cacheEnabled" value="true"/>
  13. <setting name="lazyLoadingEnabled" value="true"/>
  14. <setting name="multipleResultSetsEnabled" value="true"/>
  15. <setting name="useColumnLabel" value="true"/>
  16. <setting name="useGeneratedKeys" value="false"/>
  17. <setting name="autoMappingBehavior" value="PARTIAL"/>
  18. <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  19. <setting name="defaultExecutorType" value="SIMPLE"/>
  20. <setting name="defaultStatementTimeout" value="25"/>
  21. <setting name="defaultFetchSize" value="100"/>
  22. <setting name="safeRowBoundsEnabled" value="false"/>
  23. <setting name="mapUnderscoreToCamelCase" value="false"/>
  24. <setting name="localCacheScope" value="SESSION"/>
  25. <setting name="jdbcTypeForNull" value="OTHER"/>
  26. <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
  27. </settings>
  28. <!--typeAliases-->
  29. <typeAliases>
  30. <typeAlias alias="Author" type="domain.blog.Author"/>
  31. <typeAlias alias="Blog" type="domain.blog.Blog"/>
  32. <typeAlias alias="Comment" type="domain.blog.Comment"/>
  33. <typeAlias alias="Post" type="domain.blog.Post"/>
  34. <typeAlias alias="Section" type="domain.blog.Section"/>
  35. <typeAlias alias="Tag" type="domain.blog.Tag"/>
  36. </typeAliases>
  37. <typeAliases>
  38. <package name="domain.blog"/>
  39. </typeAliases>
  40. <!--typeHandlers-->
  41. <typeHandlers>
  42. <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
  43. </typeHandlers>
  44. <typeHandlers>
  45. <package name="org.mybatis.example"/>
  46. </typeHandlers>
  47. <typeHandlers>
  48. <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="java.math.RoundingMode"/>
  49. </typeHandlers>
  50. <!--objectFactory-->
  51. <objectFactory type="org.mybatis.example.ExampleObjectFactory">
  52. <property name="someProperty" value="100"/>
  53. </objectFactory>
  54. <!--objectWrapperFactory-->
  55. <!--reflectorFactory-->
  56. <!--plugins-->
  57. <plugins>
  58. <plugin interceptor="org.mybatis.example.ExamplePlugin">
  59. <property name="someProperty" value="100"/>
  60. </plugin>
  61. </plugins>
  62. <!--environments-->
  63. <environments default="development">
  64. <environment id="development">
  65. <transactionManager type="JDBC">
  66. <property name="..." value="..."/>
  67. </transactionManager>
  68. <dataSource type="POOLED">
  69. <property name="driver" value="${driver}"/>
  70. <property name="url" value="${url}"/>
  71. <property name="username" value="${username}"/>
  72. <property name="password" value="${password}"/>
  73. </dataSource>
  74. </environment>
  75. </environments>
  76. <!--databaseIdProvider-->
  77. <databaseIdProvider type="DB_VENDOR" />
  78. <databaseIdProvider type="DB_VENDOR">
  79. <property name="SQL Server" value="sqlserver"/>
  80. <property name="DB2" value="db2"/>
  81. <property name="Oracle" value="oracle" />
  82. </databaseIdProvider>
  83. <!--mappers-->
  84. <mappers>
  85. <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
  86. <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
  87. <mapper resource="org/mybatis/builder/PostMapper.xml"/>
  88. </mappers>
  89. <mappers>
  90. <mapper url="file:///var/mappers/AuthorMapper.xml"/>
  91. <mapper url="file:///var/mappers/BlogMapper.xml"/>
  92. <mapper url="file:///var/mappers/PostMapper.xml"/>
  93. </mappers>
  94. <mappers>
  95. <mapper class="org.mybatis.builder.AuthorMapper"/>
  96. <mapper class="org.mybatis.builder.BlogMapper"/>
  97. <mapper class="org.mybatis.builder.PostMapper"/>
  98. </mappers>
  99. <mappers>
  100. <package name="org.mybatis.builder"/>
  101. </mappers>
  102. </configuration>

重复的节点是不同的配置方式。每个节点只写一次就好。

这样就可以对应这个看了。按照类中方法的顺序。

1.加载properties属性。

  1. /**
  2. * 加载properties节点
  3. * 注意这里并没有加载,properties节点的子节点信息,而是在settingsElement进行加载。
  4. * @param context
  5. * @throws Exception
  6. */
  7. private void propertiesElement(XNode context) throws Exception {
  8. if (context != null) {
  9. // 获取所有子节点
  10. Properties defaults = context.getChildrenAsProperties();
  11. // 获取resource元素
  12. String resource = context.getStringAttribute("resource");
  13. // 获取url元素
  14. String url = context.getStringAttribute("url");
  15. if (resource != null && url != null) {
  16. throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference. Please specify one or the other.");
  17. }
  18. // 如果resource和url同时配置了的话,不可以同时配置(上面)。
  19. if (resource != null) {
  20. // 将resource对应的文件中的所有属性加载到defaults(Properties)中。
  21. defaults.putAll(Resources.getResourceAsProperties(resource));
  22. } else if (url != null) {
  23. //将url对应的文件中的所有属性加载到defaults(Properties)中。
  24. defaults.putAll(Resources.getUrlAsProperties(url));
  25. }
  26. // 将configuration中的配置和读取的配置合并。
  27. Properties vars = configuration.getVariables();
  28. if (vars != null) {
  29. defaults.putAll(vars);
  30. }
  31. parser.setVariables(defaults);
  32. configuration.setVariables(defaults);
  33. }
  34. }
  1. 加载Setting节点的配置信息
  1. // 加载settings配置信息。
  2. private Properties settingsAsProperties(XNode context) {
  3. if (context == null) {
  4. return new Properties();
  5. }
  6. // 获取子节点。
  7. Properties props = context.getChildrenAsProperties();
  8. // 检测所有的配置对Configuration类都是已知的。
  9. MetaClass metaConfig = MetaClass.forClass(Configuration.class, localReflectorFactory);
  10. for (Object key : props.keySet()) {
  11. if (!metaConfig.hasSetter(String.valueOf(key))) {
  12. throw new BuilderException("The setting " + key + " is not known. Make sure you spelled it correctly (case sensitive).");
  13. }
  14. }
  15. return props;
  16. }
  17. // 将设置的放到configuration中。
  18. private void loadCustomVfs(Properties props) throws ClassNotFoundException {
  19. String value = props.getProperty("vfsImpl");
  20. if (value != null) {
  21. String[] clazzes = value.split(",");
  22. for (String clazz : clazzes) {
  23. if (!clazz.isEmpty()) {
  24. @SuppressWarnings("unchecked")
  25. Class<? extends VFS> vfsImpl = (Class<? extends VFS>) Resources.classForName(clazz);
  26. configuration.setVfsImpl(vfsImpl);
  27. }
  28. }
  29. }
  30. }

这里有点疑问。loadCustomVfs,这里的Vfs指的是什么??

但是可以看出,这里并没有加载我们在配置文件里面书写的setting,而是以后进行的加载。

3.加载别名

  1. /**
  2. * 解析别名
  3. * 详见:TypeAliasRegistry.java
  4. * @param parent
  5. */
  6. private void typeAliasesElement(XNode parent) {
  7. if (parent != null) {
  8. // 遍历typeAliases下的所有子节点。
  9. for (XNode child : parent.getChildren()) {
  10. // 如果是子节点的名字是package.
  11. if ("package".equals(child.getName())) {
  12. // 获取子节点中package节点的name元素属性。
  13. String typeAliasPackage = child.getStringAttribute("name");
  14. // 把该包中的所有类设置别名。把类名装换成小写。设置到typeAliasRegistry实体中。
  15. configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);
  16. } else {
  17. // 如果不是package,那就是:typeAlias,获取typeAlias的alias属性和type属性值。
  18. String alias = child.getStringAttribute("alias");
  19. String type = child.getStringAttribute("type");
  20. try {
  21. Class<?> clazz = Resources.classForName(type);
  22. if (alias == null) {
  23. typeAliasRegistry.registerAlias(clazz);
  24. } else {
  25. typeAliasRegistry.registerAlias(alias, clazz);
  26. }
  27. } catch (ClassNotFoundException e) {
  28. throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e);
  29. }
  30. }
  31. }
  32. }
  33. }
  1. 解析插件配置
  1. // 加载插件的配置
  2. private void pluginElement(XNode parent) throws Exception {
  3. if (parent != null) {
  4. for (XNode child : parent.getChildren()) {
  5. // 获取interceptor属性值。
  6. String interceptor = child.getStringAttribute("interceptor");
  7. Properties properties = child.getChildrenAsProperties();
  8. // 利用反射,获取执行拦截器的实例。
  9. Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).newInstance();
  10. interceptorInstance.setProperties(properties);
  11. // 将拦截添加到configuration中。
  12. // 可想而知,它将拦截器添加到拦截器链中。
  13. configuration.addInterceptor(interceptorInstance);
  14. }
  15. }
  16. }

一下这个几个节点,不知道有什么作用,就暂时一笔带过。

  1. // 加载对象工厂,同plugins逻辑
  2. private void objectFactoryElement(XNode context) throws Exception {
  3. if (context != null) {
  4. String type = context.getStringAttribute("type");
  5. Properties properties = context.getChildrenAsProperties();
  6. ObjectFactory factory = (ObjectFactory) resolveClass(type).newInstance();
  7. factory.setProperties(properties);
  8. configuration.setObjectFactory(factory);
  9. }
  10. }
  11. // 加载对象包装器工厂,同plugins逻辑
  12. private void objectWrapperFactoryElement(XNode context) throws Exception {
  13. if (context != null) {
  14. String type = context.getStringAttribute("type");
  15. ObjectWrapperFactory factory = (ObjectWrapperFactory) resolveClass(type).newInstance();
  16. configuration.setObjectWrapperFactory(factory);
  17. }
  18. }
  19. //加载反射工厂,同plugins逻辑
  20. private void reflectorFactoryElement(XNode context) throws Exception {
  21. if (context != null) {
  22. String type = context.getStringAttribute("type");
  23. ReflectorFactory factory = (ReflectorFactory) resolveClass(type).newInstance();
  24. configuration.setReflectorFactory(factory);
  25. }
  26. }
  1. 正式加载setting配置文件。
  1. private void settingsElement(Properties props) throws Exception {
  2. // 是否自动映射column和field。默认为只自动映射简单字段,不会映射关联对象。见:AutoMappingBehavior
  3. configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));
  4. //指定检测自动映射目标的未知列(或未知属性类型)时的行为。 就是当column和类字段不一致的时候,mybatis会做些什么?
  5. // 默认为:什么都不做。见:AutoMappingUnknownColumnBehavior
  6. configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));
  7. // 是否启用缓存。默认启用。
  8. configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));
  9. // 反射工厂。
  10. configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory")));
  11. // 是否延迟加载。
  12. configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));
  13. // 是否使用积极的懒加载
  14. configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), false));
  15. // 是否使用多个结果集
  16. configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));
  17. // 是否使用列标签
  18. configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));
  19. // 是否使用主键生成策略
  20. configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));
  21. // 使用执行器的类型。
  22. configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE")));
  23. // Sql语句执行超时间,默认不超时。
  24. configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null));
  25. // 不知道干什么用的。
  26. configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null));
  27. // 是否自动匹配下划线转换成驼峰命名法。很重要,经常用。
  28. configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false));
  29. // 是否启动安全的行界。
  30. configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false));
  31. // 本地缓存范围。默认为Session
  32. configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION")));
  33. // 干甚用??
  34. configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER")));
  35. // 延迟加载触发器的方法;默认有equals,clone,hashCode,toString
  36. configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString"));
  37. // 安全结果处理程序已启用 干甚用??
  38. configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));
  39. // 默认的脚本语言,干甚用??
  40. configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage")));
  41. // 设置类型处理器。
  42. @SuppressWarnings("unchecked")
  43. Class<? extends TypeHandler> typeHandler = (Class<? extends TypeHandler>) resolveClass(props.getProperty("defaultEnumTypeHandler"));
  44. configuration.setDefaultEnumTypeHandler(typeHandler);
  45. // 在属性值为null的是否调用call。难道是为null是就不会调用set方法。。
  46. configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));
  47. // 使用实际参数。
  48. configuration.setUseActualParamName(booleanValueOf(props.getProperty("useActualParamName"), true));
  49. // 是否返回空行实例。默认为false。
  50. configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));
  51. // log前缀。
  52. configuration.setLogPrefix(props.getProperty("logPrefix"));
  53. // 设置答应log。
  54. @SuppressWarnings("unchecked")
  55. Class<? extends Log> logImpl = (Class<? extends Log>) resolveClass(props.getProperty("logImpl"));
  56. configuration.setLogImpl(logImpl);
  57. // 设置配置工厂。
  58. configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));
  59. }
  60. /**
  61. * 读取环境元素
  62. * @param context
  63. * @throws Exception
  64. */
  65. private void environmentsElement(XNode context) throws Exception {
  66. // 对应着xml文件来看:
  67. if (context != null) {
  68. if (environment == null) {
  69. environment = context.getStringAttribute("default");
  70. }
  71. // 读取所有的<environments>子节点
  72. for (XNode child : context.getChildren()) {
  73. String id = child.getStringAttribute("id");
  74. // 只读取设置好的default,或者初始化时设置好的环境
  75. if (isSpecifiedEnvironment(id)) {
  76. TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
  77. DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
  78. DataSource dataSource = dsFactory.getDataSource();
  79. Environment.Builder environmentBuilder = new Environment.Builder(id)
  80. .transactionFactory(txFactory)
  81. .dataSource(dataSource);
  82. configuration.setEnvironment(environmentBuilder.build());
  83. }
  84. }
  85. }
  86. }
  1. 加载DB类别提供者,,可以根据不同的db类型,打印不同的query语句。
  1. /**
  2. * 加载 DB id Provider 元素
  3. * DB-id-Provider: 不同数据库支持者。
  4. * @param context
  5. * @throws Exception
  6. */
  7. private void databaseIdProviderElement(XNode context) throws Exception {
  8. DatabaseIdProvider databaseIdProvider = null;
  9. if (context != null) {
  10. String type = context.getStringAttribute("type");
  11. // awful patch to keep backward compatibility
  12. if ("VENDOR".equals(type)) {
  13. type = "DB_VENDOR";
  14. }
  15. Properties properties = context.getChildrenAsProperties();
  16. databaseIdProvider = (DatabaseIdProvider) resolveClass(type).newInstance();
  17. databaseIdProvider.setProperties(properties);
  18. }
  19. Environment environment = configuration.getEnvironment();
  20. if (environment != null && databaseIdProvider != null) {
  21. String databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource());
  22. configuration.setDatabaseId(databaseId);
  23. }
  24. }

8.加载类型处理器

  1. /**
  2. * 加载类型处理器
  3. * @param parent
  4. * @throws Exception
  5. */
  6. private void typeHandlerElement(XNode parent) throws Exception {
  7. if (parent != null) {
  8. for (XNode child : parent.getChildren()) {
  9. if ("package".equals(child.getName())) {
  10. String typeHandlerPackage = child.getStringAttribute("name");
  11. typeHandlerRegistry.register(typeHandlerPackage);
  12. } else {
  13. String javaTypeName = child.getStringAttribute("javaType");
  14. String jdbcTypeName = child.getStringAttribute("jdbcType");
  15. String handlerTypeName = child.getStringAttribute("handler");
  16. Class<?> javaTypeClass = resolveClass(javaTypeName);
  17. JdbcType jdbcType = resolveJdbcType(jdbcTypeName);
  18. Class<?> typeHandlerClass = resolveClass(handlerTypeName);
  19. if (javaTypeClass != null) {
  20. if (jdbcType == null) {
  21. typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);
  22. } else {
  23. typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
  24. }
  25. } else {
  26. typeHandlerRegistry.register(typeHandlerClass);
  27. }
  28. }
  29. }
  30. }
  31. }

加载mapper映射文件:

  1. /**
  2. * 加载mapper映射文件。
  3. * @param parent
  4. * @throws Exception
  5. */
  6. private void mapperElement(XNode parent) throws Exception {
  7. if (parent != null) {
  8. for (XNode child : parent.getChildren()) {
  9. if ("package".equals(child.getName())) {
  10. String mapperPackage = child.getStringAttribute("name");
  11. configuration.addMappers(mapperPackage);
  12. } else {
  13. String resource = child.getStringAttribute("resource");
  14. String url = child.getStringAttribute("url");
  15. String mapperClass = child.getStringAttribute("class");
  16. if (resource != null && url == null && mapperClass == null) {
  17. ErrorContext.instance().resource(resource);
  18. InputStream inputStream = Resources.getResourceAsStream(resource);
  19. XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
  20. mapperParser.parse();
  21. } else if (resource == null && url != null && mapperClass == null) {
  22. ErrorContext.instance().resource(url);
  23. InputStream inputStream = Resources.getUrlAsStream(url);
  24. XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
  25. mapperParser.parse();
  26. } else if (resource == null && url == null && mapperClass != null) {
  27. Class<?> mapperInterface = Resources.classForName(mapperClass);
  28. configuration.addMapper(mapperInterface);
  29. } else {
  30. throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
  31. }
  32. }
  33. }
  34. }
  35. }

好了,这样这个加载mybatis-config.xml的类就看完了。

### 最后
如果你觉得写的还不错,就关注下公众号呗,关注后,有点小礼物回赠给你。
你可以获得5000+电子书,java,springCloud,adroid,python等各种视频教程,IT类经典书籍,各种软件的安装及破解教程。
希望一块学习,一块进步!
20190901125800286.jpg

发表评论

表情:
评论列表 (有 0 条评论,250人围观)

还没有评论,来说两句吧...

相关阅读