mybatis-generator原始碼解讀系列(三):配置讀取
阿新 • • 發佈:2019-01-07
概述:
配置讀取是程式碼生成的基礎工作,主要就是把xml中的元資料讀取到記憶體中,供後面的程式碼生成邏輯使用
相關類
1、ConfigurationParser
功能
主要用來將xml配置檔案讀取到記憶體,獲取根節點,根據根節點的屬性值,選擇對應的子節點的配置解析器
程式碼解讀:
1)讀取xml
// dcoument 組裝器 DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(new ParserEntityResolver()); // 例項化一個錯誤處理類,處理的錯誤和警告資訊會以list形式儲存 ParserErrorHandler handler = new ParserErrorHandler(warnings, parseErrors); builder.setErrorHandler(handler); // 使用w3c 文件解析 Document document = null; try { // 將記憶體檔案轉換為w3c文件物件 document = builder.parse(inputSource); } catch (SAXParseException e) { // 拋除自定義xml轉換錯誤異常 throw new XMLParserException(parseErrors); } catch (SAXException e) { // 其他異常處理 if (e.getException() == null) { parseErrors.add(e.getMessage()); } else { parseErrors.add(e.getException().getMessage()); } } // 有錯的情況下,丟擲異常終止執行 if (parseErrors.size() > 0) { throw new XMLParserException(parseErrors); }
2、解析根節點,根據元資料值獲取子節點解析器
// 返回的配置檔案物件 Configuration config; // 獲取根節點 Element rootNode = document.getDocumentElement(); // 獲取文件型別 DocumentType docType = document.getDoctype(); if (rootNode.getNodeType() == Node.ELEMENT_NODE && docType.getPublicId().equals( XmlConstants.IBATOR_CONFIG_PUBLIC_ID)) { config = parseIbatorConfiguration(rootNode); } else if (rootNode.getNodeType() == Node.ELEMENT_NODE && docType.getPublicId().equals( XmlConstants.MYBATIS_GENERATOR_CONFIG_PUBLIC_ID)) { // -//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN // 該DTD執行此分支,也就是mybatis處理分支 config = parseMyBatisGeneratorConfiguration(rootNode); } else { throw new XMLParserException(getString("RuntimeError.5")); //$NON-NLS-1$ } if (parseErrors.size() > 0) { throw new XMLParserException(parseErrors); }
2、MyBatisGeneratorConfigurationParser
功能:
主要實現子節點解析工作,同時把所有的元資料載入到記憶體,供後續解析使用
程式碼解讀:
1)屬性、資料庫類驅動以及上下解析
2)解析上下文,將所有的元資料載入到記憶體上下文,生成程式碼時使用這些資料(如:生成哪些類、報名、類名等)if ("properties".equals(childNode.getNodeName())) { //$NON-NLS-1$ parseProperties(configuration, childNode); } else if ("classPathEntry".equals(childNode.getNodeName())) { //$NON-NLS-1$ // 轉換類路徑節點,轉換的元素賦值給配置物件 parseClassPathEntry(configuration, childNode); } else if ("context".equals(childNode.getNodeName())) { //$NON-NLS-1$ // 轉換上下文節點,轉換的元素賦值給配置物件 parseContext(configuration, childNode); }
// 獲取context的所有屬性以及值
Properties attributes = parseAttributes(node);
String defaultModelType = attributes.getProperty("defaultModelType"); //$NON-NLS-1$
String targetRuntime = attributes.getProperty("targetRuntime"); //$NON-NLS-1$
String introspectedColumnImpl = attributes
.getProperty("introspectedColumnImpl"); //$NON-NLS-1$
String id = attributes.getProperty("id"); //$NON-NLS-1$
ModelType mt = defaultModelType == null ? null : ModelType
.getModelType(defaultModelType);
System.err.println("parseContext | 獲取預設的模型型別:" + mt);
// 例項化一個上下文,並將模型型別傳入構造方法,如果為null則是適用condition
Context context = new Context(mt);
context.setId(id);
if (stringHasValue(introspectedColumnImpl)) {
context.setIntrospectedColumnImpl(introspectedColumnImpl);
}
if (stringHasValue(targetRuntime)) {
context.setTargetRuntime(targetRuntime);
}
// 將上下文放到配置物件中
configuration.addContext(context);
// 獲取上下問的子節點,遍歷轉換
NodeList nodeList = node.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node childNode = nodeList.item(i);
if (childNode.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
if ("property".equals(childNode.getNodeName())) { //$NON-NLS-1$
parseProperty(context, childNode);
} else if ("plugin".equals(childNode.getNodeName())) { //$NON-NLS-1$
parsePlugin(context, childNode);
} else if ("commentGenerator".equals(childNode.getNodeName())) { //$NON-NLS-1$
// 註釋轉換
parseCommentGenerator(context, childNode);
} else if ("jdbcConnection".equals(childNode.getNodeName())) { //$NON-NLS-1$
parseJdbcConnection(context, childNode);
} else if ("connectionFactory".equals(childNode.getNodeName())) { //$NON-NLS-1$
parseConnectionFactory(context, childNode);
} else if ("javaModelGenerator".equals(childNode.getNodeName())) { //$NON-NLS-1$
parseJavaModelGenerator(context, childNode);
} else if ("javaTypeResolver".equals(childNode.getNodeName())) { //$NON-NLS-1$
parseJavaTypeResolver(context, childNode);
} else if ("sqlMapGenerator".equals(childNode.getNodeName())) { //$NON-NLS-1$
parseSqlMapGenerator(context, childNode);
} else if ("javaClientGenerator".equals(childNode.getNodeName())) { //$NON-NLS-1$
parseJavaClientGenerator(context, childNode);
} else if ("table".equals(childNode.getNodeName())) { //$NON-NLS-1$
parseTable(context, childNode);
}
3)解讀每個具體屬性到各自記憶體配置物件中
JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration();
context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration);
Properties attributes = parseAttributes(node);
String type = attributes.getProperty("type"); //$NON-NLS-1$
String targetPackage = attributes.getProperty("targetPackage"); //$NON-NLS-1$
String targetProject = attributes.getProperty("targetProject"); //$NON-NLS-1$
String implementationPackage = attributes
.getProperty("implementationPackage"); //$NON-NLS-1$
javaClientGeneratorConfiguration.setConfigurationType(type);
javaClientGeneratorConfiguration.setTargetPackage(targetPackage);
javaClientGeneratorConfiguration.setTargetProject(targetProject);
javaClientGeneratorConfiguration
.setImplementationPackage(implementationPackage);
NodeList nodeList = node.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node childNode = nodeList.item(i);
if (childNode.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
if ("property".equals(childNode.getNodeName())) { //$NON-NLS-1$
parseProperty(javaClientGeneratorConfiguration, childNode);
}
}
※ 上面解讀具體解讀的程式碼都雷同,首先需要各自節點的一個配置類(JavaClientGeneratorConfiguration ),然後將資料讀取到該類的例項物件中,同時將該物件注入到記憶體上下文中(Context)。