代码之家  ›  专栏  ›  技术社区  ›  Wolfgang Fahl

为什么pluginManager.getExtensions的结果为空?

  •  0
  • Wolfgang Fahl  · 技术社区  · 7 年前

    在尝试使用PF4J时,我创建了中概述的必要零件

    https://github.com/pf4j/pf4j

    1. 扩展扩展点的接口
    2. 插件
    3. 装有舱单的罐子

    我已经通过JUnit测试对此进行了测试,在那里我可以调试其他似乎工作正常的部分。请参阅下面的调试日志。

    我也看过 https://github.com/pf4j/pf4j/issues/21 并激活Eclipse注释处理,但没有任何积极影响。

    1.扩展扩展点的接口

    public interface ClickHandler extends ExtensionPoint {
    ...
    
    }
    

    2.插件

    public class MBClickHandlerPlugin extends Plugin {
    
      /**
       * construct me
       * @param wrapper
       */
      public MBClickHandlerPlugin(PluginWrapper wrapper) {
        super(wrapper);
      }
    
      @Extension
      public static class  MBClickHandler implements ClickHandler {
    
    
      }
    }
    

    3.带有清单的Jar

    unzip -q -c target/com.bitplan.mb-0.0.1.jar META-INF/MANIFEST.MF
    Manifest-Version: 1.0
    Plugin-Dependencies: 
    Plugin-Id: com.bitplan.mb
    Built-By: wf
    Plugin-Provider: BITPlan GmbH
    Plugin-Version: 0.0.1
    Plugin-Class: com.bitplan.mb.MBClickHandlerPlugin
    Created-By: Apache Maven 3.5.2
    Build-Jdk: 1.8.0_152
    

    4.插件加载和激活

      /**
       * activate the plugins requested on the command line
       */
      public void activatePlugins() {
        pluginManager = new DefaultPluginManager();
    
        for (String plugin : plugins) {
          Path pluginPath = Paths.get(plugin);
          pluginManager.loadPlugin(pluginPath);
        }
        pluginManager.startPlugins();
    
        List<ClickHandler> clickHandlers = pluginManager
            .getExtensions(ClickHandler.class);
        for (ClickHandler clickHandler : clickHandlers) {
          installClickHandler(clickHandler);
        }
      }
    

    调试日志

    22 [main] DEBUG org.pf4j.CompoundPluginDescriptorFinder  - Try to continue with the next finder
    22 [main] DEBUG org.pf4j.CompoundPluginDescriptorFinder  - 'org.pf4j.ManifestPluginDescriptorFinder@73d4cc9e' is applicable for plugin '/Users/wf/Documents/workspace/com.bitplan.mb/target/com.bitplan.mb-0.0.1.jar'
    24 [main] DEBUG org.pf4j.AbstractPluginManager  - Found descriptor PluginDescriptor [pluginId=com.bitplan.mb, pluginClass=com.bitplan.mb.MBClickHandlerPlugin, version=0.0.1, provider=BITPlan GmbH, dependencies=[], description=, requires=*, license=null]
    24 [main] DEBUG org.pf4j.AbstractPluginManager  - Class 'com.bitplan.mb.MBClickHandlerPlugin' for plugin '/Users/wf/Documents/workspace/com.bitplan.mb/target/com.bitplan.mb-0.0.1.jar'
    24 [main] DEBUG org.pf4j.AbstractPluginManager  - Loading plugin '/Users/wf/Documents/workspace/com.bitplan.mb/target/com.bitplan.mb-0.0.1.jar'
    24 [main] DEBUG org.pf4j.CompoundPluginLoader  - 'org.pf4j.DefaultPluginLoader@6366ebe0' is not applicable for plugin '/Users/wf/Documents/workspace/com.bitplan.mb/target/com.bitplan.mb-0.0.1.jar'
    24 [main] DEBUG org.pf4j.CompoundPluginLoader  - 'org.pf4j.JarPluginLoader@44f75083' is applicable for plugin '/Users/wf/Documents/workspace/com.bitplan.mb/target/com.bitplan.mb-0.0.1.jar'
    25 [main] DEBUG org.pf4j.PluginClassLoader  - Add 'file:/Users/wf/Documents/workspace/com.bitplan.mb/target/com.bitplan.mb-0.0.1.jar'
    25 [main] DEBUG org.pf4j.AbstractPluginManager  - Loaded plugin '/Users/wf/Documents/workspace/com.bitplan.mb/target/com.bitplan.mb-0.0.1.jar' with class loader 'org.pf4j.PluginClassLoader@43d7741f'
    25 [main] DEBUG org.pf4j.AbstractPluginManager  - Creating wrapper for plugin '/Users/wf/Documents/workspace/com.bitplan.mb/target/com.bitplan.mb-0.0.1.jar'
    25 [main] DEBUG org.pf4j.AbstractPluginManager  - Created wrapper 'PluginWrapper [descriptor=PluginDescriptor [pluginId=com.bitplan.mb, pluginClass=com.bitplan.mb.MBClickHandlerPlugin, version=0.0.1, provider=BITPlan GmbH, dependencies=[], description=, requires=*, license=null], pluginPath=/Users/wf/Documents/workspace/com.bitplan.mb/target/com.bitplan.mb-0.0.1.jar]' for plugin '/Users/wf/Documents/workspace/com.bitplan.mb/target/com.bitplan.mb-0.0.1.jar'
    26 [main] DEBUG org.pf4j.DependencyResolver  - Graph: 
       com.bitplan.mb -> []
    26 [main] DEBUG org.pf4j.DependencyResolver  - Plugins order: [com.bitplan.mb]
    27 [main] INFO org.pf4j.AbstractPluginManager  - Plugin 'com.bitplan.mb@0.0.1' resolved
    27 [main] INFO org.pf4j.AbstractPluginManager  - Start plugin 'com.bitplan.mb@0.0.1'
    27 [main] DEBUG org.pf4j.DefaultPluginFactory  - Create instance for plugin 'com.bitplan.mb.MBClickHandlerPlugin'
    28 [main] DEBUG org.pf4j.AbstractExtensionFinder  - Finding extensions of extension point 'com.bitplan.uml2mxgraph.ClickHandler'
    28 [main] DEBUG org.pf4j.LegacyExtensionFinder  - Reading extensions storages from classpath
    28 [main] DEBUG org.pf4j.AbstractExtensionFinder  - No extensions found
    28 [main] DEBUG org.pf4j.LegacyExtensionFinder  - Reading extensions storages from plugins
    28 [main] DEBUG org.pf4j.LegacyExtensionFinder  - Reading extensions storage from plugin 'com.bitplan.mb'
    28 [main] DEBUG org.pf4j.LegacyExtensionFinder  - Cannot find 'META-INF/extensions.idx'
    28 [main] DEBUG org.pf4j.AbstractExtensionFinder  - No extensions found
    28 [main] DEBUG org.pf4j.AbstractExtensionFinder  - Finding extensions of extension point 'com.bitplan.uml2mxgraph.ClickHandler' for plugin 'null'
    28 [main] DEBUG org.pf4j.AbstractExtensionFinder  - Finding extensions of extension point 'com.bitplan.uml2mxgraph.ClickHandler' for plugin 'com.bitplan.mb'
    29 [main] DEBUG org.pf4j.AbstractExtensionFinder  - Found 0 extensions for extension point 'com.bitplan.uml2mxgraph.ClickHandler
    

    1 回复  |  直到 7 年前
        1
  •  1
  •   Wolfgang Fahl    7 年前

    解决办法#1

    使用定制的PluginManager

    pluginManager = new JarPluginManager(this.getClass().getClassLoader());
    

    JarPluginManager源代码:

    import java.nio.file.Path;
    
    import org.pf4j.DefaultPluginManager;
    import org.pf4j.JarPluginLoader;
    import org.pf4j.ManifestPluginDescriptorFinder;
    import org.pf4j.PluginClassLoader;
    import org.pf4j.PluginDescriptor;
    import org.pf4j.PluginDescriptorFinder;
    import org.pf4j.PluginLoader;
    import org.pf4j.PluginManager;
    
    /**
     * see https://github.com/pf4j/pf4j/issues/249 see
     * https://pf4j.org/doc/class-loading.html
     * 
     * @author wf
     *
     */
    public class JarPluginManager extends DefaultPluginManager {
      public static class ParentClassLoaderJarPluginLoader extends JarPluginLoader {
        static ClassLoader parentClassLoader;
    
        /**
         * 
         * @param pluginManager
         */
        public ParentClassLoaderJarPluginLoader(PluginManager pluginManager) {
          super(pluginManager);
        }
    
        static PluginClassLoader pluginClassLoader;
    
        @Override
        public ClassLoader loadPlugin(Path pluginPath,
            PluginDescriptor pluginDescriptor) {
          if (pluginClassLoader == null) {
            boolean parentFirst=true;
            pluginClassLoader = new PluginClassLoader(pluginManager,
                pluginDescriptor, parentClassLoader,parentFirst);
          }
          pluginClassLoader.addFile(pluginPath.toFile());
    
          return pluginClassLoader;
        }
      }
    
      /**
       * construct me with the given classloader
       * @param classLoader
       */
      public JarPluginManager(ClassLoader classLoader) {
        ParentClassLoaderJarPluginLoader.parentClassLoader=classLoader;
        //System.setProperty("pf4j.mode", RuntimeMode.DEPLOYMENT.toString());
        //System.setProperty("pf4j.mode", RuntimeMode.DEVELOPMENT.toString());
      }
    
      @Override
      protected PluginLoader createPluginLoader() {
        // load only jar plugins
        return new ParentClassLoaderJarPluginLoader(this);
      }
    
      @Override
      protected PluginDescriptorFinder createPluginDescriptorFinder() {
        // read plugin descriptor from jar's manifest
        return new ManifestPluginDescriptorFinder();
      }
    
    }
    

    解决办法#2 如果未创建extensions.idx文件,则说明批注处理有问题。您可能希望修复问题的根源,但也可以尝试解决它:

    • https://groups.google.com/forum/#!topic/pf4j/nn20axJHpfI 指给我手动创建META-INF/extensions.idx文件,并确保静态内部类没有args构造函数。 有了这种变化,一切都正常了。

    • 文件-否则,处理程序列表中的条目将为空

    • 注意使用空参数构造函数,否则将以异常结束

    @Extension
    public static class  MBClickHandler implements ClickHandler {
      /**
       * constructor with no argument
       */
      public MBClickHandler() {
    
      }
    

    src/main/resources/META-INF/extensions.idx

    com.bitplan.mb.MBClickHandlerPlugin$MBClickHandler
    

    要检查的代码

    1. extension.idx条目的正确名称
    MBClickHandler ch=new MBClickHandler();
    File extFile=new File("src/main/resources/META-INF/extensions.idx");
    String extidx=FileUtils.readFileToString(extFile,"UTF-8");
    assertEquals(extidx,ch.getClass().getName());
    
    1. 检查扩展
    List<PluginWrapper> startedPlugins = pluginManager.getStartedPlugins();
    
        for (PluginWrapper plugin : startedPlugins) {
           String pluginId = plugin.getDescriptor().getPluginId();
           System.out.println(String.format("Extensions added by plugin '%s':", pluginId));
           Set<String> extensionClassNames = pluginManager.getExtensionClassNames(pluginId);
           for (String extension : extensionClassNames) {
               System.out.println("   " + extension);
           }
        }