概述:

        配置读取是代码生成的基础工作,主要就是把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)属性、数据库类驱动以及上下解析    

            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);
}

2)解析上下文,将所有的元数据加载到内存上下文,生成代码时使用这些数据(如:生成哪些类、报名、类名等)

        // 获取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)。