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); } }创建自定义共享事件有三条硬性要求,缺一不可:
- 共享事件必须继承
ApplicationEvent; - 共享事件必须被
@SharedEvent注解标记,否则事件不会被广播,其他插件订阅不到; - 如果想要被其他插件订阅,则需要将该事件类发布到 Maven 仓库中,供其他插件引用。
第三条是跨插件场景的前置条件:事件类本身要能被别的插件在编译期引用到,仅在本插件工程内定义是不够的。
验证与排查
判断订阅是否生效,依据文档和源码给出的事实:
- 事件是否可订阅:检查事件类上是否有
@SharedEvent注解。SharedEventDispatcher只对带注解的事件做广播,未标记的事件不会到达插件侧的监听器。 - 插件是否在运行:分发逻辑会把事件广播给所有已启动(started)且应用上下文处于 running 状态的插件,插件未启动时收不到事件。
- 监听器是否被注册:
@Component(或等效的 Bean 注册方式)必须生效,监听 Bean 未被 Spring 容器管理时监听方法不会执行。
边界说明
- 共享事件可以被核心和所有插件订阅,广播范围是整个运行中的插件集合,订阅方无法按插件名过滤;
- 核心事件(如
PostPublishedEvent、PostUpdatedEvent)由核心发布,插件只负责订阅; - 插件自定义事件若要跨插件订阅,必须把事件类发布到 Maven 仓库,这一步是其他插件引用的前提,而不是可选项。
【免费下载链接】haloHalo 是一款强大易用的开源建站工具,从个人博客、知识库,到企业官网、在线商城,Halo 都能助您轻松实现,一站式满足您的多样化建站需求。项目地址: https://gitcode.com/GitHub_Trending/ha/halo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考