MyBatis Generator 源码分析

MyBatis Generator 源码分析

资料:
文档:http://www.mybatis.org/generator/configreference/table.html
下载:https://github.com/mybatis/generator

快速开始:

List<String> warnings = new ArrayList<String>();
   boolean overwrite = true;
   File configFile = new File("generatorConfig.xml");
   ConfigurationParser cp = new ConfigurationParser(warnings);
   Configuration config = cp.parseConfiguration(configFile);
   DefaultShellCallback callback = new DefaultShellCallback(overwrite);
   MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
   myBatisGenerator.generate(null);

源码分析:
1. MyBatisGenerator 构造器:没有做特别的事情,主要就是初始化并校验配置文件。

super();
        if (configuration == null) {
            throw new IllegalArgumentException(getString("RuntimeError.2")); 
        } else {
            this.configuration = configuration;
        }
        if (shellCallback == null) {
            this.shellCallback = new DefaultShellCallback(false);
        } else {
            this.shellCallback = shellCallback;
        }
        if (warnings == null) {
            this.warnings = new ArrayList<String>();
        } else {
            this.warnings = warnings;
        }
        generatedJavaFiles = new ArrayList<GeneratedJavaFile>();
        generatedXmlFiles = new ArrayList<GeneratedXmlFile>();
        projects = new HashSet<String>();
        this.configuration.validate();
  1. 生成文件:
if (callback == null) {
            callback = new NullProgressCallback();
        }
        generatedJavaFiles.clear();
        generatedXmlFiles.clear();
        ObjectFactory.reset();
        RootClassInfo.reset();
        // 1.从配置文件中获取到上下文信息。对应配置文件的<context>标签,几乎所有的配置都在这个标签之内。
        List<Context> contextsToRun;
        if (contextIds == null || contextIds.size() == 0) {
            contextsToRun = configuration.getContexts();
        } else {
            contextsToRun = new ArrayList<Context>();
            for (Context context : configuration.getContexts()) {
                if (contextIds.contains(context.getId())) {
                    contextsToRun.add(context);
                }
            }
        }
        // 2.加载自定义的class文件,主要用于加载数据库驱动。
        if (configuration.getClassPathEntries().size() > 0) {
            ClassLoader classLoader = getCustomClassloader(configuration.getClassPathEntries());
            ObjectFactory.addExternalClassLoader(classLoader);
        }
        // 3.统计处理步骤,并调用callback对应的方法。
        int totalSteps = 0;
        for (Context context : contextsToRun) {
            totalSteps += context.getIntrospectionSteps();
        }
        callback.introspectionStarted(totalSteps);
// 4.开始处理表信息,这里是生成代码的实际处理的第一步。
        for (Context context : contextsToRun) {
            context.introspectTables(callback, warnings,
                    fullyQualifiedTableNames);
        }
        // 5.类似于第3步,通常情况下没有什么用处。
        totalSteps = 0;
        for (Context context : contextsToRun) {
            totalSteps += context.getGenerationSteps();
        }
        callback.generationStarted(totalSteps);
// 6.开始生成文件,这一步是生成实际的文件。
        for (Context context : contextsToRun) {
            context.generateFiles(callback, generatedJavaFiles,
                    generatedXmlFiles, warnings);
        }
        // 7.将文件写到本地。
        if (writeFiles) {
            callback.saveStarted(generatedXmlFiles.size()
                + generatedJavaFiles.size());
            for (GeneratedXmlFile gxf : generatedXmlFiles) {
                projects.add(gxf.getTargetProject());
                writeGeneratedXmlFile(gxf, callback);
            }
            for (GeneratedJavaFile gjf : generatedJavaFiles) {
                projects.add(gjf.getTargetProject());
                writeGeneratedJavaFile(gjf, callback);
            }
            for (String project : projects) {
                shellCallback.refreshProject(project);
            }
        }
        callback.done();

a) 处理表信息:Context. introspectTables 方法 Context 的构造器的逻辑也没有特别的,只是简单的初始化。

introspectedTables = new ArrayList<IntrospectedTable>();
        // 1.创建类型处理器,主要用于处理数据库数据类型与java类型的对应关系
        JavaTypeResolver javaTypeResolver = ObjectFactory
                .createJavaTypeResolver(this, warnings);
        Connection connection = null;
        try {
            callback.startTask(getString("Progress.0")); 
            connection = getConnection();
            //2.构造出数据库信息类来,这个构造器只是初始化了一些变量。
            DatabaseIntrospector databaseIntrospector = new DatabaseIntrospector(
                    this, connection.getMetaData(), javaTypeResolver, warnings);
            for (TableConfiguration tc : tableConfigurations) {
                String tableName = composeFullyQualifiedTableName(tc.getCatalog(), tc
                                .getSchema(), tc.getTableName(), '.');
                if (fullyQualifiedTableNames != null
                        && fullyQualifiedTableNames.size() > 0
                        && !fullyQualifiedTableNames.contains(tableName)) {
                    continue;
                }
                if (!tc.areAnyStatementsEnabled()) {
                    warnings.add(getString("Warning.0", tableName)); 
                    continue;
                }
                callback.startTask(getString("Progress.1", tableName)); 
                // 3.根据配置创建出IntrospectedTable类,此时已经将数据库栏位名称对应的字段名以及数据库数据类型对应的java类型都已经计算出来了。
                List<IntrospectedTable> tables = databaseIntrospector
                        .introspectTables(tc);
                if (tables != null) {
                    introspectedTables.addAll(tables);
                }
                callback.checkCancel();
            }
        } finally {
            closeConnection(connection);
        }

b) 生成文件:Context.generateFiles

pluginAggregator = new PluginAggregator();
        // 1.处理插件信息.暂时先忽略
        for (PluginConfiguration pluginConfiguration : pluginConfigurations) {
            Plugin plugin = ObjectFactory.createPlugin(this,
                    pluginConfiguration);
            if (plugin.validate(warnings)) {
                pluginAggregator.addPlugin(plugin);
            } else {
                warnings.add(getString("Warning.24", //$NON-NLS-1$
                        pluginConfiguration.getConfigurationType(), id));
            }
        }
        if (introspectedTables != null) {
            for (IntrospectedTable introspectedTable : introspectedTables) {
                callback.checkCancel();
                //2.初始化相关属性.
                introspectedTable.initialize();
                //3.计算出需要使用的生成器.
                introspectedTable.calculateGenerators(warnings, callback);
                generatedJavaFiles.addAll(introspectedTable
                        .getGeneratedJavaFiles());
                generatedXmlFiles.addAll(introspectedTable
                        .getGeneratedXmlFiles());
                generatedJavaFiles.addAll(pluginAggregator
                        .contextGenerateAdditionalJavaFiles(introspectedTable));
                generatedXmlFiles.addAll(pluginAggregator
                        .contextGenerateAdditionalXmlFiles(introspectedTable));
            }
        }
        generatedJavaFiles.addAll(pluginAggregator
                .contextGenerateAdditionalJavaFiles());
        generatedXmlFiles.addAll(pluginAggregator
                .contextGenerateAdditionalXmlFiles());

c) 写入到本地文件中:调用GeneratedJavaFile的getFormattedContent方法获得java文件内容;调用GeneratedXmlFile的getFormattedContent方法获得xml文件的内容。

  1. Generator:下面重点看下文件生成器,mybatis-generator提供了很多文件生成器,有mybatis xml文件生成器,也有java文件生成器,其中java文件生成器也有很多种,这里只看几个常用的简单的。
    a) DAOGenerator:在getCompilationUnits方法中构造出TopLevelClass和Interface,并根据之前构造的信息向类和接口中添加一系列的方法,此不详述,详细参见源码。在写出文件是调用的getFormattedContent实际上就是这两个类的方法。
    b) JavaMapperGenerator:在这个类中的getCompilationUnits方法只构造出了Interface,其他与DAOGenerator类似。
    c) XMLMapperGenerator:在getDocument方法中构造出了一个document。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
【目的】如果您希望弄懂框架的原理,但是苦于不知道如何读框架源码?希望该课程能够通过带领大家阅读源码的方式,了解源码是如何阅读的。该课程选择了一个比较小,比较简单的框架入门,相信大家应该也用过该工具——mybatis generator【内容】该课程内容如下,列出了具体时间,便于复习:第一课:mybatis-generator源码分析-解析配置这节课分为如下几段:【00:00-05:00】:介绍源码阅读的方法【05:00-08:00】:简介mybatis-generator的使用 【08:00-27:30】:mybatis-generator包一览 【27:30-结束】:解析配置源码解读 【总结】所在的位置:1.第一次总结【34:15】。2.第二次总结【52:40】 涉及的【设计思路】和【设计模式】:1.模板模式【15:30】。2.xml解析的对象设计+组合模式:【37:00】。3.策略模式:【45:40】 第二课:mybatis-generator源码分析-生成文件 这节课分为如下几段:        1. 【00:00-10:20】:上节课内容回顾       2. 【10:20-42:20】:如何从数据库中获取元数据信息       3. 【42:20-结束】:生成文件 【总结】所在的位置:1.第一次总结【37:45】。2.第二次总结【56:25】 涉及的【设计思路】和【设计模式】:1、简单工厂方法模式【35:20】。2、聚合的设计思想【44:00】。 第三课:mybatis-generator源码分析-总结 这节课分为如下几段:        1. 【00:00-01:00】: 设计思路总结         2. 【01:00-02:50】:配置解析总结         3. 【02:50-03:55】: 从数据库获取信息总结         4. 【03:55-结束】: 文件的生成总结         

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜗牛_snail

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值