mybatis基本配置之properties

来源:互联网 发布:深圳淘宝网店培训 编辑:程序博客网 时间:2024/06/05 17:06

有些同学可能没有找到源码,只是看jar包中的class文件或者反编译出来看,这里放一个链接mybatis源码可以下载下来看,比较方便。
这篇记录下配置文件的中的properties节点的使用。
一般在配置文件中使用如下:

<properties resource="jdbc.properties">    <property name="username" value="root" />    <property name="password" value="123" /></properties>

或者配合environment节点下的datasource使用

<dataSource type="POOLED">    <property name="driver" value="${jdbc.driverClassName}" />    <property name="url" value="${jdbc.url}" />    <property name="username" value="${jdbc.username}" />    <property name="password" value="${jdbc.password}" /></dataSource>

那么我们来看下,这个properties节点是如何解析的。
首先还是来到我们熟悉的类XMLConfigBuilder.java
parseConfiguration()解析各个节点

 private void parseConfiguration(XNode root) {    try {      Properties settings = settingsAsPropertiess(root.evalNode("settings"));      //issue #117 read properties first      //解析properties节点      propertiesElement(root.evalNode("properties"));      loadCustomVfs(settings);      typeAliasesElement(root.evalNode("typeAliases"));      pluginElement(root.evalNode("plugins"));      objectFactoryElement(root.evalNode("objectFactory"));      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));      reflectionFactoryElement(root.evalNode("reflectionFactory"));      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);    }  }

那么在解析properties节点的时候顺序是什么样,如果我们既配置读取外部文件又在xml中进行配置,最终会用哪个呢?
在propertiesElement()方法中我们可以看到:

private void propertiesElement(XNode context) throws Exception {    if (context != null) {        //先解析xml中Property几点      Properties defaults = context.getChildrenAsProperties();      //在解析外部文件      String resource = context.getStringAttribute("resource");      String url = context.getStringAttribute("url");      //resource和url不能同时使用      if (resource != null && url != null) {        throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference.  Please specify one or the other.");      }      //把外部文件放入defaults中,意味着如果与xml中的name同名,将会被外部文件的值覆盖      if (resource != null) {        defaults.putAll(Resources.getResourceAsProperties(resource));      } else if (url != null) {        defaults.putAll(Resources.getUrlAsProperties(url));      }      Properties vars = configuration.getVariables();      if (vars != null) {        defaults.putAll(vars);      }      parser.setVariables(defaults);      configuration.setVariables(defaults);    }  }

有此我们看到,有限读取xml中property的节点值,但是如果外部配置文件中有相同的名字,这个值将会被覆盖。
在解析property的节点解析如下:

 public Properties getChildrenAsProperties() {    Properties properties = new Properties();    //获取子节点    for (XNode child : getChildren()) {      //获取name      String name = child.getStringAttribute("name");      //获取value      String value = child.getStringAttribute("value");      if (name != null && value != null) {      //放入map中        properties.setProperty(name, value);      }    }    return properties;  }

对于我们经常用到占位符${},mybatis是如何解析的呢?
在解析node的方法中,

private Properties parseAttributes(Node n) {    Properties attributes = new Properties();    NamedNodeMap attributeNodes = n.getAttributes();    if (attributeNodes != null) {      for (int i = 0; i < attributeNodes.getLength(); i++) {        Node attribute = attributeNodes.item(i);        //解析节点的值        String value = PropertyParser.parse(attribute.getNodeValue(), variables);        attributes.put(attribute.getNodeName(), value);      }    }    return attributes;  }
public static String parse(String string, Properties variables) {    VariableTokenHandler handler = new VariableTokenHandler(variables);    //传入"${"和"}"开始结束符    GenericTokenParser parser = new GenericTokenParser("${", "}", handler);    return parser.parse(string);  }
 public String parse(String text) {    final StringBuilder builder = new StringBuilder();    final StringBuilder expression = new StringBuilder();    if (text != null && text.length() > 0) {      char[] src = text.toCharArray();      int offset = 0;      // search open token      int start = text.indexOf(openToken, offset);      while (start > -1) {        if (start > 0 && src[start - 1] == '\\') {          // this open token is escaped. remove the backslash and continue.          builder.append(src, offset, start - offset - 1).append(openToken);          offset = start + openToken.length();        } else {          // found open token. let's search close token.          expression.setLength(0);          builder.append(src, offset, start - offset);          offset = start + openToken.length();          int end = text.indexOf(closeToken, offset);          while (end > -1) {            if (end > offset && src[end - 1] == '\\') {              // this close token is escaped. remove the backslash and continue.              expression.append(src, offset, end - offset - 1).append(closeToken);              offset = end + closeToken.length();              end = text.indexOf(closeToken, offset);            } else {              expression.append(src, offset, end - offset);              offset = end + closeToken.length();              break;            }          }          if (end == -1) {            // close token was not found.            builder.append(src, start, src.length - start);            offset = src.length;          } else {            builder.append(handler.handleToken(expression.toString()));            offset = end + closeToken.length();          }        }        start = text.indexOf(openToken, offset);      }      if (offset < src.length) {        builder.append(src, offset, src.length - offset);      }    }    return builder.toString();  }
 public String handleToken(String content) {     //获取占位符内字段和配置文件相同的字段进行替换      if (variables != null && variables.containsKey(content)) {        return variables.getProperty(content);      }      return "${" + content + "}";    }

在这个方法中进行解析和赋值。

0 1