> Click to learn the configuration method of the properties element
After the basic environment of Mybatis for parsing XML is ready, we can finally usher in the first real configuration file parsing operation.
propertiesElement(root.evalNode("properties"));
The propertiesElement method reads the configuration of the properties element in the mybatis global configuration file and converts it to a properties object.
The properties element is one of the 11 child nodes in the configuration element. Its DTD is defined as follows:
<!--ELEMENT properties (property*)--> <!--ATTLIST properties resource CDATA #IMPLIED url CDATA #IMPLIED -->
It allows multiple property child nodes and can also configure the resource and url properties, but the resource and url properties cannot exist at the same time, The definition of the property sub node is as follows:
<!--ELEMENT property EMPTY--> <!--ATTLIST property name CDATA #REQUIRED value CDATA #REQUIRED -->
The property element is made up of name and value, so it can be parsed into a Properties object. In the following specific parsing process, we will see that Mybatis provides corresponding parsing operations for these three different configurations.
/** * Resolving Properties Tags * * @param context Properties node * @throws Exception abnormal */ private void propertiesElement(XNode context) throws Exception { // The user has configured the properties node if (context != null) { // Get the name and value values of the Property node under Properties, and convert the Properties Property Properties defaults = context.getChildrenAsProperties(); // Get referenced resources String resource = context.getStringAttribute("resource"); String url = context.getStringAttribute("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."); } if (resource != null) { // Load *. Properties resource profile defaults.putAll(Resources.getResourceAsProperties(resource)); } else if (url != null) { // Load *. Properties resource profile defaults.putAll(Resources.getUrlAsProperties(url)); } // Get the property configuration passed in by user code Properties vars = configuration.getVariables(); if (vars != null) { // Merge property configuration defaults.putAll(vars); } // Refresh the variable references in the parser for subsequent parsing parser.setVariables(defaults); // Sync to Mybatis settings configuration.setVariables(defaults); } }
First, get all the property sub nodes under the properties object, and generate a property instance accordingly.
// Get the name and value values of the Property node under Properties, and convert the Properties Property Properties defaults = context.getChildrenAsProperties();
among context.getChildrenAsProperties() code is as follows:
/** * Gets all the child nodes under the specified package element, and after reading their name and value Properties, converts them to Properties objects. * */ public Properties getChildrenAsProperties() { Properties properties = new Properties(); for (XNode child : getChildren()) { // Read name and value properties String name = child.getStringAttribute("name"); String value = child.getStringAttribute("value"); if (name != null && value != null) { // If there are both name and value attributes, save them properties.setProperty(name, value); } } return properties; }
Its function is to get all the element nodes under the current node. After reading their name and value Properties, they are converted into Properties objects. The getChildren() method in the code is used to filter out the effective set of element nodes:
public List<xnode> getChildren() { List<xnode> children = new ArrayList<>(); // Get all child nodes NodeList nodeList = node.getChildNodes(); if (nodeList != null) { for (int i = 0, n = nodeList.getLength(); i < n; i++) { Node node = nodeList.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { // Filter out child nodes children.add(new XNode(xpathParser, node, variables)); } } } return children; }
After processing the property sub node of properties, mybatis will obtain the resource and url properties of properties respectively.
mybatis first verifies that both cannot exist at the same time.
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."); }
Then load the corresponding resource file according to the value of the resource/url property and convert its content into a property object and save it to the property object obtained in the previous step.
if (resource != null) { // Load *. Properties resource profile defaults.putAll(Resources.getResourceAsProperties(resource)); } else if (url != null) { // Load *. Properties resource profile defaults.putAll(Resources.getUrlAsProperties(url)); }
Then take out the existing variables in the Configuration, which are passed in by the user code, and save them to the Properties object as well.
// Get the property configuration passed in by user code Properties vars = configuration.getVariables(); if (vars != null) { // Merge property configuration defaults.putAll(vars); }
In fact, it is not difficult to understand the attribute configuration of Mybatis through the loading order of appeals. The effective priority is from high to low: Parameters set at startup - > configuration pointed to by the url/resource property of properties in mybatis main configuration file - > property configuration of properties in mybatis main configuration file.
At this stage, all the global attribute configurations have been loaded. The next step is to use these attributes.
First, update the global variable reference in xpathParser, and then use it when parsing the file.
// Refresh the variable references in the parser for subsequent parsing parser.setVariables(defaults);
Then save these global properties to Configuration, and the parsing operation of the properties element is completed.
// Sync to Mybatis settings configuration.setVariables(defaults);
Add:
In the above step of loading the corresponding resource file according to the value of the resource/url property and converting its content into a Properties object, we have involved a Resources object, which is a tool class used by mybatis to simplify resource access.
There is a ClassLoaderWrapper type attribute in the Resources object, which is the wrapper class of ClassLoader defined in mybatis. It holds multiple different ClassLoader implementations internally. When users try to get Resources through ClassLoaderWrapper, changing the wrapper class will try to use multiple classloaders to load Resources.
The implementation of Resources and ClassLoaderWrapper are relatively simple. If you are interested, you can check the source code yourself, and we will not go into details here.
Pay attention to me and learn more together
</xnode></xnode>