# FrameGen **Repository Path**: frailty/framegen ## Basic Information - **Project Name**: FrameGen - **Description**: 一个轻量级的 Java 代码生成工具。SPI模块化的探索项目 - **Primary Language**: Java - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-06-26 - **Last Updated**: 2026-07-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # FrameGen > 一个轻量级的 Java 代码生成工具,支持从数据库表结构自动生成 Entity、Mapper、Service 等代码。 [![License](https://img.shields.io/badge/license-MIT-blue.svg)](http://opensource.org/licenses/MIT) [![Java](https://img.shields.io/badge/Java-8+-green.svg)](https://www.java.com/) [![Gitee](https://img.shields.io/badge/Gitee-frailty/frame--gen-red.svg)](https://gitee.com/frailty/framegen) ## 特性 - 🚀 **零配置启动** - 通过 API 简单调用即可生成代码 - 🎯 **多框架支持** - 支持 Spring、Solon 等主流框架 - 📦 **多 ORM 适配** - 支持 MyBatis、MyBatis-Plus、MyBatis-Flex - 🏗️ **SPI 扩展机制** - 支持自定义 Enricher 和 Renderer - 📝 **ST4 模板引擎** - 内置强大的模板渲染能力 - 🦾 **Lombok 支持** - 可选生成 Lombok 注解 - 📄 **TypeScript 支持** - 可选生成 TypeScript 类型定义 - ⚙️ **灵活的包名配置** - 支持自定义包结构和命名后缀 ## 规划中的特性 - 🎨 **Kotlin 支持** - 可选生成 Kotlin 代码(重新开发中) --- ## 插件式扩展机制 FrameGen 采用 **SPI (Service Provider Interface)** 机制实现插件式扩展,核心思想是"接口定义 + 服务加载",使得框架本身与具体实现解耦,用户可以替换或扩展任意组件。 ### 核心扩展点 FrameGen 定义了以下四类核心扩展点: | 扩展点 | 接口 | 说明 | 默认实现 | |--------|------|------|----------| | **元数据增强器** | `TableContextEnricher` | 根据数据库表结构生成各类元数据 (Entity/Mapper/Service 等) | 内置 enricher | | **模板渲染器** | `TemplateRenderer` | 将元数据渲染为代码文件 | ST4Renderer | | **类型转换器** | `TypeConverter` | 将 JDBC 类型映射为 Java 类型 | 内置默认实现 | | **增强钩子** | `EnrichExtensionHook` | 在 Enricher 执行前后插入自定义逻辑 | 无 | ### SPI 服务配置文件 在 `src/main/resources/META-INF/services/` 目录下创建以**接口全限定名**命名的文件: ``` src/main/resources/ └── META-INF/ └── services/ ├── org.framegen.common.enricher.TableContextEnricher # 元数据增强器 ├── org.framegen.common.render.TemplateRenderer # 模板渲染器 ├── org.framegen.common.coverter.TypeConverter # 类型转换器 └── org.framegen.common.enricher.EnrichExtensionHook # 增强钩子 ``` 文件内容为实现类的全限定名(每行一个): ```properties # org.framegen.common.enricher.TableContextEnricher com.example.MyCustomEntityEnricher com.example.MyCustomMapperEnricher # org.framegen.common.render.TemplateRenderer io.github.frailty9.framegen.engine.st4.St4Renderer ``` ### 扩展点详解 #### 1. TableContextEnricher(元数据增强器) 负责将数据库表结构转换为代码生成所需的元数据对象。 ```java public abstract class TableContextEnricher { // 返回该 Enricher 处理的类型 protected abstract ClassType getClassType(); // 核心增强逻辑 protected abstract void enrichCore(Context context, TableContext tableContext); // 模板方法,包含 before/after 钩子调用 public void enrich(Context context, TableContext tableContext) { // 1. 执行 before 钩子 enrichHooks.forEach(hook -> hook.beforeEnrich(context, tableContext)); // 2. 执行核心增强逻辑 enrichCore(context, tableContext); // 3. 执行 after 钩子 enrichHooks.forEach(hook -> hook.afterEnrich(context, tableContext)); // 4. 处理父类/接口导入 // ... } } ``` **示例:自定义 EntityEnricher** ```java public class MyEntityEnricher extends TableContextEnricher { @Override protected ClassType getClassType() { return ClassType.ENTITY; } @Override protected void enrichCore(Context context, TableContext tableContext) { Table table = tableContext.getTable(); EntityClassMeta entityCM = EntityClassMeta.builder() .className("com.example.entity." + StrUtil.toPascalCase(table.getTableName())) .build(); // 自定义逻辑:添加 Swagger 注解 entityCM.addAnnotations("ApiModel"); entityCM.addImports("io.swagger.annotations.ApiModel"); tableContext.assembleMeta(getClassType(), entityCM); } } ``` #### 2. TemplateRenderer(模板渲染器) 负责将 ClassMeta 元数据渲染为实际代码文件。 ```java public interface TemplateRenderer { /** * 初始化渲染器 * @param templateResourcePath 模板资源路径(如 "templates/entity.st") * @param delimiterStartChar 分隔符开始字符(如 '<') * @param delimiterStopChar 分隔符结束字符(如 '>') */ void init(String templateResourcePath, char delimiterStartChar, char delimiterStopChar); /** * 渲染到文件 */ default void render(File outputFile, ClassMeta classMeta) throws IOException { // 创建目录、写入文件... } /** * 渲染到 Writer */ void render(Writer writer, ClassMeta classMeta, Map properties) throws IOException; } ``` **ST4 模板示例** ```st package ; ; }> /** }> */ }; separator="\n"> public class extends { /** */ private ; }>} ``` #### 3. TypeConverter(类型转换器) 将 JDBC 类型代码转换为 Java 类型。 ```java public interface TypeConverter { default Class convert(int jdbcType) { switch (jdbcType) { case Types.INTEGER: return Integer.class; case Types.VARCHAR: return String.class; // ... default: return Object.class; } } } ``` **示例:自定义类型映射** ```java public class MyTypeConverter implements TypeConverter { @Override public Class convert(int jdbcType) { // 自定义映射规则 if (jdbcType == Types.DATE) { return java.util.Date.class; // 改为使用 java.util.Date } return TypeConverter.super.convert(jdbcType); } } ``` #### 4. EnrichExtensionHook(增强钩子) 在 Enricher 执行前后注入自定义逻辑,适合添加统一的切面逻辑。 ```java public interface EnrichExtensionHook { ClassType getClassType(); // 可选:Enrich 之前执行 default void beforeEnrich(Context context, TableContext tableContext) {} // 可选:Enrich 之后执行 default void afterEnrich(Context context, TableContext tableContext) {} } ``` **示例:添加审计字段** ```java public class AuditFieldHook implements EnrichExtensionHook { @Override public ClassType getClassType() { return ClassType.ENTITY; } @Override public void afterEnrich(Context context, TableContext tableContext) { EntityClassMeta entity = tableContext.getRenderMeta(ClassType.ENTITY); // 统一添加审计字段 entity.addAttributes( ClassAttributeMeta.builder() .name("createTime") .type("LocalDateTime") .build(), ClassAttributeMeta.builder() .name("updateTime") .type("LocalDateTime") .build() ); } } ``` ### 完整扩展流程 ``` ┌─────────────────────────────────────────────────────────────────┐ │ FrameGen 核心 │ │ │ │ ┌──────────────┐ SPI ┌─────────────────────────────┐ │ │ │ EnricherFactory │ ────────→ │ TableContextEnricher 实现 │ │ │ │ │ │ - EntityEnricher │ │ │ │ │ │ - MapperEnricher │ │ │ └──────────────┘ │ - ServiceEnricher │ │ │ │ │ - CustomEnricher (用户) │ │ │ ↓ enrich() └─────────────────────────────┘ │ │ ┌──────────────┐ SPI ┌─────────────────────────────┐ │ │ │RendererFactory│ ─────────→ │ TemplateRenderer 实现 │ │ │ │ │ │ - St4Renderer │ │ │ └──────────────┘ │ - CustomRenderer (用户) │ │ │ │ └─────────────────────────────┘ │ │ ↓ render() │ │ ┌──────────────┐ │ │ │ Output │ ───────────────────────────────────────────→│ │ └──────────────┘ 生成的代码文件 │ │ │ └─────────────────────────────────────────────────────────────────┘ ``` ### 注意事项 1. **SPI 唯一性**:`getSingle()` 方法要求每个扩展点只能有**一个**实现,否则抛出异常 2. **无参构造**:所有 SPI 实现类必须提供无参构造方法 3. **构造器缓存**:SpiUtils 会缓存构造器以提升性能 4. **优先级**:通过 SPI 文件中的顺序可以间接控制加载优先级 ## 模块结构 ``` framegen/ ├── framegen-common # 公共组件 ├── framegen-core # 核心模块 ├── framework-integrations # 框架集成 │ ├── framegen-framework-spring │ └── framegen-framework-solon ├── orm-adapters # ORM 适配器 │ ├── framegen-orm-mybatis │ ├── framegen-orm-mybatis-plus │ └── framegen-orm-mybatis-flex ├── template-engines # 模板引擎 │ └── framegen-engine-st4 └── starters # 快速启动器 ├── framegen-starter # 基础启动器 ├── framegen-spring-starter # Spring 启动器 ├── framegen-solon-starter # Solon 启动器 ├── framegen-starter-mybatis # MyBatis 启动器 ├── framegen-starter-mybatis-plus # MyBatis-Plus 启动器 ├── framegen-starter-mybatis-flex # MyBatis-Flex 启动器 ├── framegen-spring-starter-mybatis-plus └── framegen-solon-starter-mybatis-flex ``` ## 快速开始 ### 添加依赖 使用 MyBatis-Plus 和 Spring 的示例: ```xml io.github.frailty9 framegen-spring-starter-mybatis-plus 2.1.0 ``` ### 编写代码生成器 ```java public class Generator { public static void main(String[] args) { FrameGenEntry.create(jdbc -> { jdbc.url("jdbc:mysql://localhost:3306/your_database"); jdbc.username("root"); jdbc.password("your_password"); }) // 设置输出路径 .outRootPath(Paths.get("src/main/java")) // 包名配置 .packageConfig(pkg -> { pkg.entity("com.example.entity"); pkg.mapper("com.example.mapper"); pkg.service("com.example.service"); pkg.serviceImpl("com.example.service.impl"); }) // 命名后缀配置 .namingSuffix(suffix -> { suffix.entity("Entity"); suffix.mapper("Mapper"); suffix.service("Service"); suffix.serviceImpl("ServiceImpl"); }) // 生成开关(可选,默认全部生成) .generateSwitch(sw -> { sw.controller(false); // 不生成 Controller }) // 表过滤 .includes("sys_user", "sys_role") // .excludes("sys_log") // 启用 Lombok .enableLombok(true) // 执行生成 .execute(); } } ``` ### 完整 API 参考 详细的配置选项和 API 使用方法请查阅 [API.md](./API.md)。 ## 支持的数据库 理论上支持所有通过 JDBC 驱动的关系型数据库,默认使用 HikariCP 连接池。 已验证: - ✅ MySQL - ✅ PostgreSQL - ✅ Oracle(待验证) ## 技术栈 - **Java** 8+ - **Maven** 3.6+ - **HikariCP** 3.4.5 - 连接池 - **ST4** 4.3.4 - 模板引擎 - **Lombok** 1.18.38 - 注解处理 ## 许可证 本项目采用 [MIT License](http://opensource.org/licenses/MIT) 开源。 ## 开发者 - **花殇** (Frailty) - ydl9263@qq.com ## Gitee - 仓库地址: https://gitee.com/frailty/framegen - Issues: https://gitee.com/frailty/framegen/issues