From 49ea6fbdecb1feb6a3e502cfe945d98195193d28 Mon Sep 17 00:00:00 2001 From: guqing <38999863+guqing@users.noreply.github.com> Date: Mon, 18 Jul 2022 10:56:10 +0800 Subject: [PATCH] feat: plugin class is registered as a bean at startup (#2255) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #### What type of PR is this? /kind feature /milestone 2.0 /area core #### What this PR does / why we need it: 插件 plugin.yaml 中不用在写 pluginClass 属性,插件的生命周期类通过标注 `@Component` 注解在启动时通过 PluginApplicationContext 依赖注入并创建实例,这得益于每个插件都有一个单独的 PluginApplicationContext 插件启动时可以将PluginWrapper 放到 Context 以支撑 pluginClass 实例的创建 ```yaml apiVersion: plugin.halo.run/v1alpha1 kind: Plugin metadata: # The name defines how the plugin is invoked,A unique name name: PluginTemplate spec: pluginClass: run.halo.template.TemplatePlugin ``` 现在只需要如下方式即可无需配置 pluginClass ```java @Component public class TemplatePlugin extends BasePlugin {} ``` #### Which issue(s) this PR fixes: Fixes # #### Special notes for your reviewer: /cc @halo-dev/sig-halo #### Does this PR introduce a user-facing change? ```release-note None ``` --- .../run/halo/app/core/extension/Plugin.java | 4 +- .../reconciler/PluginReconciler.java | 2 +- .../java/run/halo/app/plugin/BasePlugin.java | 2 +- .../halo/app/plugin/BasePluginFactory.java | 48 +++++++++++++++++++ .../halo/app/plugin/HaloPluginManager.java | 6 +++ .../plugin/PluginApplicationInitializer.java | 2 + .../plugin/YamlPluginDescriptorFinder.java | 2 +- .../reconciler/PluginReconcilerTest.java | 2 + .../halo/app/plugin/YamlPluginFinderTest.java | 2 +- 9 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 src/main/java/run/halo/app/plugin/BasePluginFactory.java diff --git a/src/main/java/run/halo/app/core/extension/Plugin.java b/src/main/java/run/halo/app/core/extension/Plugin.java index 53701e51b..67803f3d5 100644 --- a/src/main/java/run/halo/app/core/extension/Plugin.java +++ b/src/main/java/run/halo/app/core/extension/Plugin.java @@ -16,7 +16,6 @@ import org.pf4j.PluginState; import org.springframework.lang.NonNull; import run.halo.app.extension.AbstractExtension; import run.halo.app.extension.GVK; -import run.halo.app.plugin.BasePlugin; /** * A custom resource for Plugin. @@ -74,7 +73,8 @@ public class Plugin extends AbstractExtension { */ private String requires = "*"; - private String pluginClass = BasePlugin.class.getName(); + @Deprecated + private String pluginClass; private Boolean enabled = false; diff --git a/src/main/java/run/halo/app/core/extension/reconciler/PluginReconciler.java b/src/main/java/run/halo/app/core/extension/reconciler/PluginReconciler.java index 0205a0596..d02254392 100644 --- a/src/main/java/run/halo/app/core/extension/reconciler/PluginReconciler.java +++ b/src/main/java/run/halo/app/core/extension/reconciler/PluginReconciler.java @@ -173,7 +173,7 @@ public class PluginReconciler implements Reconciler { private void ensureSpecUpToDateWhenDevelopmentMode(PluginWrapper pluginWrapper, Plugin oldPlugin) { - if (!RuntimeMode.DEPLOYMENT.equals(pluginWrapper.getRuntimeMode())) { + if (RuntimeMode.DEPLOYMENT.equals(pluginWrapper.getRuntimeMode())) { return; } YamlPluginFinder yamlPluginFinder = new YamlPluginFinder(); diff --git a/src/main/java/run/halo/app/plugin/BasePlugin.java b/src/main/java/run/halo/app/plugin/BasePlugin.java index b0476792a..7568fd836 100644 --- a/src/main/java/run/halo/app/plugin/BasePlugin.java +++ b/src/main/java/run/halo/app/plugin/BasePlugin.java @@ -35,7 +35,7 @@ public class BasePlugin extends Plugin { return applicationContext; } - public HaloPluginManager getPluginManager() { + private HaloPluginManager getPluginManager() { return (HaloPluginManager) getWrapper().getPluginManager(); } } diff --git a/src/main/java/run/halo/app/plugin/BasePluginFactory.java b/src/main/java/run/halo/app/plugin/BasePluginFactory.java new file mode 100644 index 000000000..805f7e99f --- /dev/null +++ b/src/main/java/run/halo/app/plugin/BasePluginFactory.java @@ -0,0 +1,48 @@ +package run.halo.app.plugin; + +import java.util.Optional; +import lombok.extern.slf4j.Slf4j; +import org.pf4j.Plugin; +import org.pf4j.PluginFactory; +import org.pf4j.PluginWrapper; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; + +/** + * The default implementation for PluginFactory. + *
Get a {@link BasePlugin} instance from the {@link PluginApplicationContext}.
+ * + * @author guqing + * @since 2.0.0 + */ +@Slf4j +public class BasePluginFactory implements PluginFactory { + + @Override + public Plugin create(PluginWrapper pluginWrapper) { + return getPluginContext(pluginWrapper) + .map(context -> { + try { + return context.getBean(BasePlugin.class); + } catch (NoSuchBeanDefinitionException e) { + log.info( + "No bean named 'basePlugin' found in the context create default instance"); + DefaultListableBeanFactory beanFactory = + context.getDefaultListableBeanFactory(); + BasePlugin pluginInstance = new BasePlugin(pluginWrapper); + beanFactory.registerSingleton(Plugin.class.getName(), pluginInstance); + return pluginInstance; + } + }) + .orElse(null); + } + + private Optional