Halo 插件如何订阅核心共享事件并发布自定义 SharedEvent
2026/9/10 18:34:27 网站建设 项目流程

Halo 插件如何订阅核心共享事件并发布自定义 SharedEvent

【免费下载链接】haloHalo 是一款强大易用的开源建站工具,从个人博客、知识库,到企业官网、在线商城,Halo 都能助您轻松实现,一站式满足您的多样化建站需求。项目地址: https://gitcode.com/GitHub_Trending/ha/halo

在开发 Halo 插件时,常见的两个需求是:一是响应核心(或其他插件)发出的事件,比如文章发布、文章更新时触发插件逻辑;二是把自己的事件暴露出去,供其他插件订阅。Halo 用共享事件(SharedEvent)机制来解决这两件事:共享事件是一种特殊的事件,可以被核心和所有插件订阅。本文基于 docs/plugin/shared-event.md 以及核心事件源码,说明在插件中订阅核心共享事件、发送事件以及创建自定义 SharedEvent 的完整做法。

先了解共享事件的判定规则

在动手写代码之前,需要明确一个关键规则:只有被@SharedEvent注解标记的事件类,才能够被其他插件或核心订阅

@SharedEvent是一个符号性注解,定义在 SharedEvent.java(自 2.0.0 引入):

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SharedEvent {}

被标记事件发布时,会被广播到插件的应用上下文。具体分发逻辑可以看 SharedEventDispatcher.java:它监听所有ApplicationEvent,当事件类上找不到@SharedEvent注解时直接跳过,只有带注解的事件才会被广播给所有已启动的插件。这意味着如果你的监听器没有触发,第一件要检查的事就是事件类是否带了@SharedEvent注解。

订阅核心已提供的共享事件

核心中已经提供了不少共享事件,例如run.halo.app.event.post.PostPublishedEvent(文章发布)、run.halo.app.event.post.PostUpdatedEvent(文章更新),这些事件由核心发布,核心和插件均可订阅。更多的核心共享事件类可以在 api/src/main/java/run/halo/app/event/ 目录下查看,例如文章删除、文章取消发布、文章可见性变化、用户登录登出等事件类。

订阅有两种方式。

方式一:实现 ApplicationListener

@Component public class PostPublishedEventListener implements ApplicationListener<PostPublishedEvent> { @Override public void onApplicationEvent(PostPublishedEvent event) { // Do something } }

方式二:使用 @EventListener 注解

@Component public class PostPublishedEventListener { @EventListener // @Async // 如果需要异步处理,可以添加此注解 public void onPostPublished(PostPublishedEvent event) { // Do something } }

两种写法都是文档给出的等效路径:ApplicationListener适合事件处理逻辑独立成类的场景;@EventListener则可以把监听方法放在任意 Spring Bean 中。如果需要异步处理事件,在@EventListener方法上追加@Async注解即可,这是文档明确给出的可选项。

在插件中发送共享事件

插件内部可以通过 Spring 的ApplicationEventPublisher来发送事件,示例如下:

@Service public class PostService { private final ApplicationEventPublisher eventPublisher; public PostService(ApplicationEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } public void publishPost(Post post) { // Do something eventPublisher.publishEvent(new PostPublishedEvent(post)); } }

通过构造函数注入ApplicationEventPublisher,在业务逻辑需要的位置调用publishEvent即可。

创建自定义 SharedEvent

如果希望插件对外暴露自己的事件供其他插件订阅,需要创建一个自定义的共享事件类:

@SharedEvent public class MySharedEvent extends ApplicationEvent { public MySharedEvent(Object source) { super(source); } }

创建自定义共享事件有三条硬性要求,缺一不可:

  1. 共享事件必须继承ApplicationEvent
  2. 共享事件必须被@SharedEvent注解标记,否则事件不会被广播,其他插件订阅不到;
  3. 如果想要被其他插件订阅,则需要将该事件类发布到 Maven 仓库中,供其他插件引用。

第三条是跨插件场景的前置条件:事件类本身要能被别的插件在编译期引用到,仅在本插件工程内定义是不够的。

验证与排查

判断订阅是否生效,依据文档和源码给出的事实:

  • 事件是否可订阅:检查事件类上是否有@SharedEvent注解。SharedEventDispatcher只对带注解的事件做广播,未标记的事件不会到达插件侧的监听器。
  • 插件是否在运行:分发逻辑会把事件广播给所有已启动(started)且应用上下文处于 running 状态的插件,插件未启动时收不到事件。
  • 监听器是否被注册@Component(或等效的 Bean 注册方式)必须生效,监听 Bean 未被 Spring 容器管理时监听方法不会执行。

边界说明

  • 共享事件可以被核心和所有插件订阅,广播范围是整个运行中的插件集合,订阅方无法按插件名过滤;
  • 核心事件(如PostPublishedEventPostUpdatedEvent)由核心发布,插件只负责订阅;
  • 插件自定义事件若要跨插件订阅,必须把事件类发布到 Maven 仓库,这一步是其他插件引用的前提,而不是可选项。

【免费下载链接】haloHalo 是一款强大易用的开源建站工具,从个人博客、知识库,到企业官网、在线商城,Halo 都能助您轻松实现,一站式满足您的多样化建站需求。项目地址: https://gitcode.com/GitHub_Trending/ha/halo

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

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

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

立即咨询