pf4j 插件加载机制

主要简单说明下pf4j 的插件加载处理
参考代码 pf4j/src/main/java/org/pf4j/AbstractPluginManager.java

加载代码

  • loadPlugins 处理
 
    加载处理
    @Override
    public void loadPlugins() {
        log.debug("Lookup plugins in '{}'", pluginsRoots);
        // check for plugins roots
        if (pluginsRoots.isEmpty()) {
            log.warn("No plugins roots configured");
            return;
        }
        pluginsRoots.forEach(path -> {
            if (Files.notExists(path) || !Files.isDirectory(path)) {
                log.warn("No '{}' root", path);
            }
        });
 
        // get all plugin paths from repository
        // 查找路径
        List<Path> pluginPaths = pluginRepository.getPluginPaths();
 
        // check for no plugins
        if (pluginPaths.isEmpty()) {
            log.info("No plugins");
            return;
        }
 
        log.debug("Found {} possible plugins: {}", pluginPaths.size(), pluginPaths);
 
        // load plugins from plugin paths
        for (Path pluginPath : pluginPaths) {
            try {
                // 加载发现到的插件,此方法比较重要
                loadPluginFromPath(pluginPath);
            } catch (PluginRuntimeException e) {
                log.error(e.getMessage(), e);
            }
        }
 
        // resolve plugins
        try {
           // 解析插件,主要是关于依赖,解析插件描述信息,然后进行插件状态的通知
            resolvePlugins();
        } catch (PluginRuntimeException e) {
            log.error(e.getMessage(), e);
        }
    }
  • loadPluginFromPath 方法
    此方法比较重要,进行了插件的查找以及插件的classloader创建,形成一个插件的基本存储,方便后续流程使用
    PluginWrapper 是一个比较重要的实体,包含了不少关于插件的元数据信息
 
 protected PluginWrapper loadPluginFromPath(Path pluginPath) {
        // Test for plugin path duplication
        String pluginId = idForPath(pluginPath);
        if (pluginId != null) {
            throw new PluginAlreadyLoadedException(pluginId, pluginPath);
        }
 
        // Retrieve and validate the plugin descriptor
        PluginDescriptorFinder pluginDescriptorFinder = getPluginDescriptorFinder();
        log.debug("Use '{}' to find plugins descriptors", pluginDescriptorFinder);
        log.debug("Finding plugin descriptor for plugin '{}'", pluginPath);
        PluginDescriptor pluginDescriptor = pluginDescriptorFinder.find(pluginPath);
        validatePluginDescriptor(pluginDescriptor);
 
        // Check there are no loaded plugins with the retrieved id
        pluginId = pluginDescriptor.getPluginId();
        if (plugins.containsKey(pluginId)) {
            PluginWrapper loadedPlugin = getPlugin(pluginId);
            throw new PluginRuntimeException("There is an already loaded plugin ({}) "
                    + "with the same id ({}) as the plugin at path '{}'. Simultaneous loading "
                    + "of plugins with the same PluginId is not currently supported.\n"
                    + "As a workaround you may include PluginVersion and PluginProvider "
                    + "in PluginId.",
                loadedPlugin, pluginId, pluginPath);
        }
 
        log.debug("Found descriptor {}", pluginDescriptor);
        String pluginClassName = pluginDescriptor.getPluginClass();
        log.debug("Class '{}' for plugin '{}'",  pluginClassName, pluginPath);
 
        // load plugin
        log.debug("Loading plugin '{}'", pluginPath);
        // 此处,保证每个插件会有一个不同的classloader,这个后续会介绍
        ClassLoader pluginClassLoader = getPluginLoader().loadPlugin(pluginPath, pluginDescriptor);
        log.debug("Loaded plugin '{}' with class loader '{}'", pluginPath, pluginClassLoader);
 
        PluginWrapper pluginWrapper = createPluginWrapper(pluginDescriptor, pluginPath, pluginClassLoader);
 
        // test for disabled plugin
        if (isPluginDisabled(pluginDescriptor.getPluginId())) {
            log.info("Plugin '{}' is disabled", pluginPath);
            pluginWrapper.setPluginState(PluginState.DISABLED);
        }
 
        // validate the plugin
        if (!isPluginValid(pluginWrapper)) {
            log.warn("Plugin '{}' is invalid and it will be disabled", pluginPath);
            pluginWrapper.setPluginState(PluginState.DISABLED);
        }
 
        log.debug("Created wrapper '{}' for plugin '{}'", pluginWrapper, pluginPath);
 
        pluginId = pluginDescriptor.getPluginId();
 
        // add plugin to the list with plugins
        plugins.put(pluginId, pluginWrapper);
        getUnresolvedPlugins().add(pluginWrapper);
 
        // add plugin class loader to the list with class loaders
        getPluginClassLoaders().put(pluginId, pluginClassLoader);
 
        return pluginWrapper;
    }

说明

以上是关于pf4j 插件加载的简单说明,实际上pf4j还包含插件的unload start stop。。。后续会介绍

参考资料

https://pf4j.org/doc/plugin-lifecycle.html
https://pf4j.org/doc/plugins.html

posted on 2022-02-16 19:16  荣锋亮  阅读(619)  评论(0编辑  收藏  举报

导航