根据mybatis调用过程 sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream); 在这个位置会通过 SqlSessionFactoryBuilder实例创建一个sqlSession
第一步查看build源码
1 public SqlSessionFactory build(InputStream inputStream) { 2 return build(inputStream, null, null); 3 }
1 public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { 2 try { 3 //对输入的xml配置进行解析匹配 4 XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); 5 return build(parser.parse()); 6 } catch (Exception e) { 7 throw ExceptionFactory.wrapException("Error building SqlSession.", e); 8 } finally { 9 //统一的异常处理类进行处理 10 ErrorContext.instance().reset(); 11 try { 12 //关闭输入流 13 inputStream.close(); 14 } catch (IOException e) { 15 // Intentionally ignore. Prefer previous error. 16 } 17 } 18 }
1 public SqlSessionFactory build(Configuration config) { 2 return new DefaultSqlSessionFactory(config); 3 }
第二步 解析XMLConfigBuilder类,即依据这两行代码XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties); build(parser.parse());
1 private XMLConfigBuilder(XPathParser parser, String environment, Properties props) { 2 super(new Configuration()); 3 ErrorContext.instance().resource("SQL Mapper Configuration"); 4 this.configuration.setVariables(props); 5 this.parsed = false; 6 this.environment = environment; 7 this.parser = parser; 8 } 9 10 public Configuration parse() { 11 if (parsed) { 12 throw new BuilderException("Each XMLConfigBuilder can only be used once."); 13 } 14 parsed = true; 15 parseConfiguration(parser.evalNode("/configuration")); 16 return configuration; 17 }
再依据这行代码parseConfiguration(parser.evalNode("/configuration"));解析配置文件
private void parseConfiguration(XNode root) { try { //解析子节点的properties文件 propertiesElement(root.evalNode("properties")); //加载用户自定义配置 Properties settings = settingsAsProperties(root.evalNode("settings")); loadCustomVfs(settings); //解析子节点typeAliases 别名 typeAliasesElement(root.evalNode("typeAliases")); //解析子节点plugins 插件 pluginElement(root.evalNode("plugins")); //解析子节点objectFactory mybatis为结果创建对象时都会用到objectFactory objectFactoryElement(root.evalNode("objectFactory")); // 解析子节点的封装对象 objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); reflectorFactoryElement(root.evalNode("reflectorFactory")); //解析settings文件的全局性配置 settingsElement(settings); //配置运行环境 environmentsElement(root.evalNode("environments")); //解析子节点配置数据库供应商 databaseIdProviderElement(root.evalNode("databaseIdProvider")); //解析对象类型处理器,处理Java的pojo类型与数据库类型的映射 typeHandlerElement(root.evalNode("typeHandlers")); //解析子节点的mappers mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } }
其中针对多次出现的 root.evalNode("environments") 得到其子节点的值
1 public XNode evalNode(String expression) { 2 return xpathParser.evalNode(node, expression); 3 }
1 public XNode evalNode(Object root, String expression) { 2 Node node = (Node) evaluate(expression, root, XPathConstants.NODE); 3 if (node == null) { 4 return null; 5 } 6 return new XNode(this, node, variables); 7 } 8 9 private Object evaluate(String expression, Object root, QName returnType) { 10 try { 11 return xpath.evaluate(expression, root, returnType); 12 } catch (Exception e) { 13 throw new BuilderException("Error evaluating XPath. Cause: " + e, e); 14 } 15 }
之后采用JXAP解析xml文件
1 /** 2 * <p>Evaluate an <code>XPath</code> expression in the specified context and return the result as the specified type.</p> 3 * 4 * <p>See "Evaluation of XPath Expressions" section of JAXP 1.3 spec 5 * for context item evaluation, 6 * variable, function and <code>QName</code> resolution and return type conversion.</p> 7 * 8 * <p>If <code>returnType</code> is not one of the types defined in {@link XPathConstants} ( 9 * {@link XPathConstants#NUMBER NUMBER}, 10 * {@link XPathConstants#STRING STRING}, 11 * {@link XPathConstants#BOOLEAN BOOLEAN}, 12 * {@link XPathConstants#NODE NODE} or 13 * {@link XPathConstants#NODESET NODESET}) 14 * then an <code>IllegalArgumentException</code> is thrown.</p> 15 * 16 * <p>If a <code>null</code> value is provided for 17 * <code>item</code>, an empty document will be used for the 18 * context. 19 * If <code>expression</code> or <code>returnType</code> is <code>null</code>, then a 20 * <code>NullPointerException</code> is thrown.</p> 21 * 22 * @param expression The XPath expression. 23 * @param item The starting context (node or node list, for example). 24 * @param returnType The desired return type. 25 * 26 * @return Result of evaluating an XPath expression as an <code>Object</code> of <code>returnType</code>. 27 * 28 * @throws XPathExpressionException If <code>expression</code> cannot be evaluated. 29 * @throws IllegalArgumentException If <code>returnType</code> is not one of the types defined in {@link XPathConstants}. 30 * @throws NullPointerException If <code>expression</code> or <code>returnType</code> is <code>null</code>. 31 */ 32 public Object evaluate(String expression, Object item, QName returnType) 33 throws XPathExpressionException { 34 if ( expression == null ) { 35 String fmsg = XSLMessages.createXPATHMessage( 36 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, 37 new Object[] {"XPath expression"} ); 38 throw new NullPointerException ( fmsg ); 39 } 40 if ( returnType == null ) { 41 String fmsg = XSLMessages.createXPATHMessage( 42 XPATHErrorResources.ER_ARG_CANNOT_BE_NULL, 43 new Object[] {"returnType"} ); 44 throw new NullPointerException ( fmsg ); 45 } 46 // Checking if requested returnType is supported. returnType need to 47 // be defined in XPathConstants 48 if ( !isSupported ( returnType ) ) { 49 String fmsg = XSLMessages.createXPATHMessage( 50 XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, 51 new Object[] { returnType.toString() } ); 52 throw new IllegalArgumentException ( fmsg ); 53 } 54 55 try { 56 57 XObject resultObject = eval( expression, item ); 58 return getResultAsType( resultObject, returnType ); 59 } catch ( java.lang.NullPointerException npe ) { 60 // If VariableResolver returns null Or if we get 61 // NullPointerException at this stage for some other reason 62 // then we have to reurn XPathException 63 throw new XPathExpressionException ( npe ); 64 } catch ( javax.xml.transform.TransformerException te ) { 65 Throwable nestedException = te.getException(); 66 if ( nestedException instanceof javax.xml.xpath.XPathFunctionException ) { 67 throw (javax.xml.xpath.XPathFunctionException)nestedException; 68 } else { 69 // For any other exceptions we need to throw 70 // XPathExpressionException ( as per spec ) 71 throw new XPathExpressionException ( te ); 72 } 73 } 74 75 } 76 77 private boolean isSupported( QName returnType ) { 78 if ( ( returnType.equals( XPathConstants.STRING ) ) || 79 ( returnType.equals( XPathConstants.NUMBER ) ) || 80 ( returnType.equals( XPathConstants.BOOLEAN ) ) || 81 ( returnType.equals( XPathConstants.NODE ) ) || 82 ( returnType.equals( XPathConstants.NODESET ) ) ) { 83 84 return true; 85 } 86 return false; 87 } 88 89 private Object getResultAsType( XObject resultObject, QName returnType ) 90 throws javax.xml.transform.TransformerException { 91 // XPathConstants.STRING 92 if ( returnType.equals( XPathConstants.STRING ) ) { 93 return resultObject.str(); 94 } 95 // XPathConstants.NUMBER 96 if ( returnType.equals( XPathConstants.NUMBER ) ) { 97 return new Double ( resultObject.num()); 98 } 99 // XPathConstants.BOOLEAN 100 if ( returnType.equals( XPathConstants.BOOLEAN ) ) { 101 return new Boolean( resultObject.bool()); 102 } 103 // XPathConstants.NODESET ---ORdered, UNOrdered??? 104 if ( returnType.equals( XPathConstants.NODESET ) ) { 105 return resultObject.nodelist(); 106 } 107 // XPathConstants.NODE 108 if ( returnType.equals( XPathConstants.NODE ) ) { 109 NodeIterator ni = resultObject.nodeset(); 110 //Return the first node, or null 111 return ni.nextNode(); 112 } 113 String fmsg = XSLMessages.createXPATHMessage( 114 XPATHErrorResources.ER_UNSUPPORTED_RETURN_TYPE, 115 new Object[] { returnType.toString()}); 116 throw new IllegalArgumentException( fmsg ); 117 }
1 private XObject eval(String expression, Object contextItem) 2 throws javax.xml.transform.TransformerException { 3 com.sun.org.apache.xpath.internal.XPath xpath = new com.sun.org.apache.xpath.internal.XPath( expression, 4 null, prefixResolver, com.sun.org.apache.xpath.internal.XPath.SELECT ); 5 com.sun.org.apache.xpath.internal.XPathContext xpathSupport = null; 6 if ( functionResolver != null ) { 7 JAXPExtensionsProvider jep = new JAXPExtensionsProvider( 8 functionResolver, featureSecureProcessing, featureManager ); 9 xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext( jep ); 10 } else { 11 xpathSupport = new com.sun.org.apache.xpath.internal.XPathContext(); 12 } 13 14 XObject xobj = null; 15 16 xpathSupport.setVarStack(new JAXPVariableStack(variableResolver)); 17 18 // If item is null, then we will create a a Dummy contextNode 19 if ( contextItem instanceof Node ) { 20 xobj = xpath.execute (xpathSupport, (Node)contextItem, 21 prefixResolver ); 22 } else { 23 xobj = xpath.execute ( xpathSupport, DTM.NULL, prefixResolver ); 24 } 25 26 return xobj; 27 }