JHipster RFC-3 解读:从传统 getter 到无歧义的优先级常量 API(Unambiguous Priorities)
2026/9/20 13:56:35 网站建设 项目流程
  • 代码生成
  • 开发工具
  • 后端
  • 前端

【免费下载链接】generator-jhipster

JHipster is a development platform to quickly generate, develop, & deploy modern web applications & microservice architectures.

项目地址:https://gitcode.com/gh_mirrors/ge/generator-jhipster
点击查看免费下载

JHipster 的生成器(generator)本质上是一系列按“优先级(priority)”排队执行的任务流,而任务如何被声明、如何避免被意外排队,直接决定了生成器代码的可读性与健壮性。本篇基于官方 RFC《JHipster-RFC-3: Unambiguous priorities API》展开,结合当前仓库中generators/base-core/priorities.ts等源码实现,为你完整讲解:为什么传统get initializing()记法有歧义、新的get [INITIALIZING_PRIORITY]()常量记法如何解决该问题,以及这套设计在当前 JHipster 代码库中最终如何落地。读完你将掌握优先级常量的定义、队列前缀机制与迁移要点,能够编写符合 JHipster 标准、无歧义且可被 Blueprint 继承的生成器任务。

背景与动机:传统优先级声明方式的歧义

JHipster 的生成器建立在 Yeoman 的优先级模型之上。在传统写法中,每个优先级都是一个以优先级名命名的 getter,例如:

get initializing() { return { initializingTask() { this._sayHello(); } } } _sayHello() { console.log('hello'); } aTaskQueuedAtDefaultPriority() { console.log('I am being executed, why? I am a default priority task.'); }

这段看似正常的代码存在两个问题(见 RFC 原文):

  1. 普通方法被意外排队:只要一个类成员函数的名字不带_前缀,JHipster/Yeoman 就会把它当作default优先级的任务自动排队执行。上面的aTaskQueuedAtDefaultPriority()只是一个普通辅助函数,却会在生成流程中被悄悄执行——开发者常常对此感到困惑(RFC 原文中那句 "why?" 正是这一困惑的写照)。
  2. 不符合 JavaScript 惯例:JavaScript 社区约定_前缀表示"私有方法",非_前缀表示普通类成员。传统记法把"是否被调度执行"建立在_前缀上,违背了这一惯例,导致类成员与任务之间的界限模糊。

RFC 的结论是:JHipster 的每个优先级都有明确用途(workflow is clear),优先级之外的任务既无必要也弊大于利,因此不应再有任何任务被默认排队到default优先级之外。我们需要一种无歧义的声明方式。

方案设计:用常量名 + 计算属性 getter 声明优先级

RFC 提出的核心方案是:用常量作为 getter 的名字(computed property name),常量的值带#前缀

get [INITIALIZING_PRIORITY]() { return { initializingTask() { this.sayHello(); } } } sayHello() { console.log('hello'); } anOrdinaryClassMember() { console.log('I am not being executed, why? I am just an ordinary function.'); }

对照传统写法,新记法的变化一目了然:

关注点传统记法RFC-3 新记法
优先级 getter 命名get initializing()get [INITIALIZING_PRIORITY]()
常量取值#前缀,如#initializing
普通类成员必须加_前缀才不会被调度保持原名即可,天然不会被调度
辅助方法_sayHello()sayHello()

新记法把"这是一个优先级任务"这一语义显式编码进常量名中:INITIALIZING_PRIORITY一看便知是优先级标识;而initializingsayHello这些名字被释放出来,可以放心地作为普通类成员使用,无需再依赖_前缀约定。RFC 指出,JHipster 的模块化生成器(modular generators)在当时已经用新记法实现,证明了其可行性。

从 RFC 到实现:优先级常量与队列前缀在源码中的落地

RFC-3 在仓库中最终落地为generators/base-core/priorities.tsgenerators/base-core/generator.ts两处核心实现。值得注意的是,实际实现中的前缀字符与 RFC 提案略有差异:RFC 建议使用#前缀(#initializing),而当前源码使用>作为优先级前缀、jhipster:作为队列前缀:

// generators/base-core/priorities.ts export const PRIORITY_PREFIX = '>'; export const QUEUE_PREFIX = 'jhipster:';

完整优先级清单

generators/base-core/priorities.ts定义了完整的优先级名称集合,分为两类:

Yeoman 传统优先级initializingpromptingconfiguringdefaultwritingtransforminstallend

JHipster 自定义优先级(通过jhipster:前缀队列注入 Yeoman 调度流程):

  • composing/composingComponent:组合其他生成器
  • loading:加载应用配置
  • composingBootstrap:组合引导生成器
  • preparing/postPreparing:准备阶段及其后处理
  • multistepTransform:多步模板变换
  • postWriting:写文件后处理
  • preConflicts:冲突解决前处理
  • postInstall:安装后处理

这些名字被统一导出为PRIORITY_NAMESPRIORITY_NAMES_LISTQUEUES,并组合成CUSTOM_PRIORITIES数组(源码中通过.reverse()控制插入顺序,保证队列按声明顺序排列),供 Yeoman 在调度时按序执行。

静态常量生成

generators/base-core/generator.ts中通过asPriority工具函数把优先级名转换为带前缀的常量:

// generators/base-core/generator.ts const asPriority = (priorityName: string) => `${PRIORITY_PREFIX}${priorityName}`; static readonly INITIALIZING = asPriority(INITIALIZING); static readonly PROMPTING = asPriority(PROMPTING); static readonly CONFIGURING = asPriority(CONFIGURING); // ... 以及 COMPOSING、LOADING、PREPARING、DEFAULT、WRITING、 // POST_WRITING、INSTALL、POST_INSTALL、END 等

于是每个优先级都对应一个>前缀的常量值(如>initializing),开发者可以直接用BaseGenerator.asPriority(name)或静态常量来声明自己的优先级 getter。

实体层面的扩展优先级

generators/base-application/priorities.ts中,基础优先级进一步扩展出面向实体生成流程的细粒度优先级,同样遵循jhipster:队列前缀约定:

  • configuringEachEntity:逐个配置实体
  • loadingEntities:加载实体
  • preparingEachEntity/preparingEachEntityField/preparingEachEntityRelationship:逐个准备实体、字段、关系
  • postPreparingEachEntity
  • writingEntities/postWritingEntities
  • loadingTranslations:加载翻译资源

这些实体级队列通过before字段精确插入到基础优先级的间隙中(例如configuringEachEntityloadingEntities之前、postPreparingEachEntitydefault之前),并由ENTITY_PRIORITY_NAMESQUEUES导出,体现了"模块化生成器"按阶段拆分任务的架构思想(可参见 RFC-6 文件结构提案)。

实战示例:新记法在生成器中的真实用法

仓库中generators/bootstrap/generator.ts是采用新记法的真实范例。它先通过静态方法生成优先级常量,再用计算属性 getter声明优先级任务:

// generators/bootstrap/generator.ts const MULTISTEP_TRANSFORM_PRIORITY = BaseGenerator.asPriority(MULTISTEP_TRANSFORM); const PRE_CONFLICTS_PRIORITY = BaseGenerator.asPriority(PRE_CONFLICTS); static readonly MULTISTEP_TRANSFORM = MULTISTEP_TRANSFORM_PRIORITY; static readonly PRE_CONFLICTS = PRE_CONFLICTS_PRIORITY; get multistepTransform(): Record<string, (this: this) => unknown> { return { queueMultistepTransform() { this.queueMultistepTransform(); }, }; } get [MULTISTEP_TRANSFORM_PRIORITY]() { return this.multistepTransform; }

这个例子演示了新记法的完整模式:

  1. BaseGenerator.asPriority(...)生成>multistepTransform常量;
  2. 写一个普通类成员multistepTransform(没有_前缀,也不会被误调度);
  3. get [MULTISTEP_TRANSFORM_PRIORITY]()把它注册到对应优先级队列中。

对比传统记法,普通方法multistepTransform与优先级 getter 职责分离、语义清晰,完全消除了"非_前缀方法被默认排队"的隐患。

迁移与影响:破坏性变更及 Blueprint 适配

RFC 明确指出这是一个破坏性变更(breaking change)

  • 传统生成器必须切换到常量记法;在 JHipster 7 中迁移时,不能直接使用#前缀(RFC 原文:they must not use the#prefix at JHipster 7),需要遵循当前仓库实际采用的>前缀方案。
  • Blueprint(蓝图)作为基于 JHipster 基类扩展的生成器,必须同步采用相同模式(Blueprints will have to adopt the same pattern),否则其优先级 getter 将无法被正确识别。
  • 若同时维护新旧两套生成器,要注意队列调度语义的差异:传统记法下任何裸方法都会进入default队列,而新记法下只有显式声明为优先级 getter 的任务才会被执行。

从源码结构看,generators/base-core/generator.ts中静态常量的集中定义,为 Blueprint 提供了一致的引用入口(BaseGenerator.INITIALIZING等),这也正是 RFC 所追求的"更传统的类实现记法"——让生成器类回归普通 JavaScript 类的表达方式。

总结与展望

RFC-3 的价值在于把"任务的调度语义"从命名约定_前缀)迁移到显式声明(常量 + 计算属性),从而:

  • 消除普通类成员被意外排队的歧义;
  • 让生成器代码遵循 JavaScript 标准惯例;
  • PRIORITY_NAMES/QUEUES/asPriority等统一抽象,支撑 JHipster 模块化生成器与 Blueprint 生态的持续演进。

当前仓库的priorities.tsgenerator.tsbootstrap/generator.ts完整实现了 RFC 的设计意图(前缀由#演变为>属于实现细节的迭代)。对于希望深入理解或二次开发 JHipster 生成器的开发者,建议按以下路径继续研读源码:

  • RFC-3 完整提案
  • 基础优先级定义与队列表
  • 优先级静态常量与 asPriority 实现
  • 实体级优先级扩展
  • 新记法实战范例(bootstrap 生成器)
  • 模块化生成器文件结构 RFC-6
  • 代码生成
  • 开发工具
  • 后端
  • 前端

【免费下载链接】generator-jhipster

JHipster is a development platform to quickly generate, develop, & deploy modern web applications & microservice architectures.

项目地址:https://gitcode.com/gh_mirrors/ge/generator-jhipster
点击查看免费下载

相关推荐

上一篇:【亲测免费】 推荐开源项目:Alipay AutoJS - 自动化脚本工具
下一篇:ESP32软件串口开发实战:基于EspSoftwareSerial的loopback测试案例终极指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询