@EventListener(ApplicationEvent.class)
    void onApplicationEvent(ApplicationEvent event) {
        if (AnnotationUtils.findAnnotation(event.getClass(), SharedEvent.class) == null) {
            return;
        }
        // we should copy the plugins list to avoid ConcurrentModificationException
        var startedPlugins = new ArrayList<>(pluginManager.getStartedPlugins());
        // broadcast event to all started plugins except the publisher
        for (var startedPlugin : startedPlugins) {
            var plugin = startedPlugin.getPlugin();
            if (!(plugin instanceof SpringPlugin springPlugin)) {
                continue;
            }
            var context = springPlugin.getApplicationContext();
            // make sure the context is running before publishing the event
            if (context instanceof Lifecycle lifecycle && lifecycle.isRunning()) {
                context.publishEvent(new HaloSharedEventDelegator(this, event));
            }
        }
    }
@Test
    void shouldUnwrapPluginSharedEventAndRepublish() {
        var event = new PluginSharedEventDelegator(this, new FakeSharedEvent(this));
        dispatcher.onApplicationEvent(event);
        verify(publisher).publishEvent(event.getDelegate());
    }