Ineed-Core 集成事件接入指南
查看内部事件、蒸馏事件、开关和监听器的具体接入契约。
浏览全部手册
本页目录
文档来源与 Markdown 原文
权威正文:ineed-core/docs/core/integration-event-guide.md。网站按工作区快照同步,原文中的历史日期和验证范围保留。
开始编码前核对同版本源码;跨仓文件引用可在源码定位目录查找。
下载 Markdown 原文 ↓文档定位
本文档说明 ineed-integration 当前已经落地的接入方式、配置规则、事件模型和业务模块的推荐用法。
当前范围覆盖标准 Manager 主链路中的 CRUD 和数据状态事件:
createupdatelogicDeletephysicsDeletedataStatusChange
已接入的执行线包括:
- 阻塞式
ineed-core-data-core - 响应式
ineed-core-data-core-reactive
暂不覆盖:
recovery- WebHook adapter
- Spring Cloud adapter
- outbox / 可靠投递
1. 当前模块关系
ineed-integration负责事件模型、开关、默认 key 解析、Spring 事件发布与蒸馏监听。ineed-core-data-core已在标准同步Manager默认实现里接入事件发送。ineed-core-data-core-reactive已在标准响应式Manager默认实现里接入同一套事件发送。- 业务模块
当前不需要改
Service主流程,只需要按需配置开关、监听事件,或者覆盖默认 key 解析。
2. 当前接入前提
2.1 标准启动方式
如果应用主类使用:
@SpringBootApplication(scanBasePackages = "com.ineed")
当前可以直接扫描到:
IntegrationConfigurationBusinessEventPublisherDistilledBusinessEventListener
这是仓库里当前 demo / test project 的默认接法。
2.2 非标准扫描方式
如果应用没有扫描 com.ineed 根包,需要显式接入:
import org.springframework.context.annotation.Import;
import com.ineed.integration.configuration.IntegrationConfiguration;
@Import(IntegrationConfiguration.class)
public class YourApplication {
}
或者把 com.ineed.integration 加入你的扫描路径。
3. 当前配置方式
3.1 YAML 示例
下面示例是“开启发送”的示例。
真实默认值仍然是:
ineed.integration.enabled = falseineed.integration.internal.enabled = falseineed.integration.distilled.enabled = false
ineed:
integration:
enabled: true
internal:
enabled: true
keys:
security.member-identity: true
distilled:
enabled: true
keys:
security.member-identity: true
3.2 Properties 示例
ineed.integration.enabled=true
ineed.integration.internal.enabled=true
ineed.integration.internal.keys[security.member-identity]=true
ineed.integration.distilled.enabled=true
ineed.integration.distilled.keys[security.member-identity]=true
3.3 判断规则
事件是否会进入发布链,当前按下面顺序判断:
ineed.integration.enabled必须为true- 对应通道
enabled必须为true - 对应
keys[eventKey]必须为true
未配置的 key 默认视为关闭。
这里的 eventKey 是兼容命名。Manifest 配置了 resourceKey 时,发布链使用 resourceKey 作为 key;旧 Manifest 只配置 eventKey 时仍按旧 key 兼容。
3.4 一个容易忽略的点
当前 shouldPublishInternal(eventKey) 的规则是:
- 只要内部通道开启了该 key,就发布内部事件
- 只要蒸馏通道开启了该 key,也会先发布内部事件
这是当前的有意设计。
原因是蒸馏事件本身依赖 InternalBusinessEvent,并且蒸馏监听器要在事务提交后再处理。
4. 默认资源键规则
当前默认解析器是 DefaultBusinessEventDefinitionResolver。
规则如下:
sourceModule取实体包名中com.ineed后面的第一个段aggregateType取实体简单类名并转换为snake_caseresourceKey注册后使用 Manifest 中的业务资源键;未注册时回退为类名.操作后缀operationKey取BusinessOperationType的资源操作键,如create、updateeventKey兼容字段;有resourceKey时等同resourceKey,旧 Manifest 仅配置eventKey时继续使用旧值
例如:
- 实体类:
com.ineed.security.authorization.memberidentity.jdbc.entity.MemberIdentity - 操作:
UPDATE - 默认 resourceKey/eventKey:
com.ineed.security.authorization.memberidentity.jdbc.entity.MemberIdentity.updated - 默认 operationKey:
update
如果实体类名本身带后缀,当前也会保留下来。
例如:
- 实体类:
MemberIdentityEntity - 默认聚合名:
member_identity_entity
如果这个默认规则不符合业务语义,可以覆盖 BusinessEventDefinitionResolver。
5. 当前事件模型
5.1 顶层结构
内部事件和蒸馏事件共用同一份 BusinessEventMessage<T>,核心字段包括:
eventIdeventKey(兼容字段,推荐与resourceKey保持一致)resourceKeyoperationKeyaggregateTypeoperationTypeentityIdtenantKeysourceModulesourceTypeoccurredAtpayload
5.2 当前 CRUD payload
当前 payload 类型是 CrudBusinessEventPayload<T>,包含:
entityIdbeforeafterdeleteMode
5.3 当前各操作的实际负载
CREATE
before = nullafter = 创建后的 VOdeleteMode = null
UPDATE
before = 修改前 VOafter = 修改后 VOdeleteMode = null
LOGIC_DELETE
before = nullafter = nulldeleteMode = LOGIC
PHYSICS_DELETE
before = nullafter = nulldeleteMode = PHYSICS
删除事件现在只保证:
entityIdtenantKeyoperationTypedeleteMode
如果后面要补删除前快照,再单独增强。
5.4 DataStatus payload
数据状态变化使用 DataStatusBusinessEventPayload,字段固定为:
idaction:追加状态位为append,移除状态位为subtractstatusFeature:DataStatusFeature枚举名,例如ENABLEDbeforeStatus:变化前的完整 byte 状态;实体原值为null时按0处理afterStatus:变化后的完整 byte 状态
Manager 先读取并校验全部目标,再比较完整状态。只有状态位实际变化的目标才会进入唯一状态处理、持久化和事件发布;空编号集合、全部幂等的命令以及未注册或关闭的事件 key 都不会发送事件。批量操作对每个实际变化的目标发送一条事件。
6. 事件时序
阻塞式主链路当前时序如下:
Manager主流程完成数据变更- 立即发布
InternalBusinessEvent DistilledBusinessEventListener用@TransactionalEventListener(phase = AFTER_COMMIT)监听- 主事务提交成功后,才发布
DistilledBusinessEvent
这意味着:
- 内部事件是事务内的 Spring 事件
- 蒸馏事件是提交后的 JVM 内事件
- 当前不保证跨进程可靠送达
响应式主链路使用同一套 IntegrationEventSupport 发布事件:
- 事件在 repository 保存 / 删除链路完成、
afterXxx钩子完成之后发布 - 数据状态事件在对应 append / subtract 持久化完成之后发布
- 发布动作发生在当前 reactive subscription 内,不要求业务
Service手工补发 - 未订阅时不会查询目标、修改状态或发布事件
- 如果业务链路接入 reactive transaction,
DistilledBusinessEvent只在事务提交后发送,回滚时不发送 - 当前不承诺跨进程可靠投递,也不承诺并发写入下的可串行化行为
7. 业务模块怎么监听
7.1 模块内协作监听内部事件
如果你要做同 JVM 的模块内协作,并且需要拿到内部标准消息,可以监听 InternalBusinessEvent<?>:
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import com.ineed.integration.event.BusinessEventMessage;
import com.ineed.integration.event.InternalBusinessEvent;
@Component
public class MemberInternalEventListener {
@EventListener
public void onInternalEvent(final InternalBusinessEvent<?> event) {
final BusinessEventMessage<?> message = event.getMessage();
if (!"security.member-identity".equals(message.getResourceKey()) || !"create".equals(message.getOperationKey())) {
return;
}
// 模块内协作逻辑
}
}
7.2 跨模块或外发前置监听蒸馏事件
如果你要做 WebHook、对外同步、跨模块桥接,优先监听 DistilledBusinessEvent<?>:
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import com.ineed.integration.event.BusinessEventMessage;
import com.ineed.integration.event.DistilledBusinessEvent;
@Component
public class MemberPrivilegeBridgeListener {
@EventListener
public void onDistilledEvent(final DistilledBusinessEvent<?> event) {
final BusinessEventMessage<?> message = event.getMessage();
if (!"security.member-identity".equals(message.getResourceKey()) || !"create".equals(message.getOperationKey())) {
return;
}
// 这里再去调用权益中心 adapter / webhook / stream bridge
}
}
推荐原则:
- 模块内同步协作:优先内部事件
- 跨模块、外发、集成边界:优先蒸馏事件
8. 业务模块怎么覆盖默认 key
如果默认 key 不够稳定,或者你不想把实体命名暴露给事件 key,可以自己提供 BusinessEventDefinitionResolver Bean:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ineed.integration.event.BusinessEventDefinitionResolver;
import com.ineed.integration.event.BusinessOperationType;
import com.ineed.integration.event.DefaultBusinessEventDefinitionResolver;
import com.ineed.integration.event.ResolvedBusinessEventDefinition;
import com.ineed.security.authorization.memberidentity.jdbc.entity.MemberIdentity;
@Configuration
public class MemberEventDefinitionConfiguration {
@Bean
public BusinessEventDefinitionResolver memberBusinessEventDefinitionResolver() {
final BusinessEventDefinitionResolver delegate = new DefaultBusinessEventDefinitionResolver();
return (entityType, operationType) -> {
if (MemberIdentity.class.equals(entityType)) {
return memberIdentityDefinition(operationType);
}
return delegate.resolve(entityType, operationType);
};
}
private static ResolvedBusinessEventDefinition memberIdentityDefinition(final BusinessOperationType operationType) {
final ResolvedBusinessEventDefinition definition = new ResolvedBusinessEventDefinition();
definition.setSourceModule("security");
definition.setAggregateType("member_identity");
definition.setOperationType(operationType);
definition.setResourceKey("security.member-identity");
definition.setOperationKey(operationType.getOperationKey());
definition.setEventKey(definition.getResourceKey());
return definition;
}
}
更推荐的实际做法是:
- 业务模块内部自己封装一层 resolver
- 未命中的实体继续委托给默认 resolver
这样不会把所有规则都重写掉。
9. 当前已经接入的发送点
当前标准链路的发送点在 Manager 主流程中,不在 Service 中。
阻塞式发送点:
CreateManager.save(...)UpdateManager.update(...)LogicDeleteManager.logicDelete(...)PhysicsDeleteManager.physicsDelete(...)
响应式发送点:
com.ineed.core.data.reactive.manager.crud.CreateManager.save(...)com.ineed.core.data.reactive.manager.crud.UpdateManager.update(...)com.ineed.core.data.reactive.manager.crud.LogicDeleteManager.logicDelete(...)com.ineed.core.data.reactive.manager.crud.PhysicsDeleteManager.physicsDelete(...)
并且发布动作都放在:
- 业务
afterXxx钩子执行完成之后 - 返回结果之前
这样可以避免业务覆写 afterXxx 时绕过底座事件。
10. 当前不建议的用法
- 不要在业务
Service里手工重复发同一类标准 CRUD 事件 - 不要把开关分散到业务模块各自配置里
- 不要直接依赖删除事件里存在完整快照,当前没有这个保证
- 不要把
DistilledBusinessEvent当成可靠消息中间件
11. 下一阶段候选
后续如果继续推进,下一批更自然的工作是:
DataStatus事件recovery事件- 删除前快照增强
- WebHook adapter
- Spring Cloud adapter
- outbox / 可靠投递
最后更新:2026-05-15
仍有疑问?按反馈清单整理复现信息 →