启用OSGi / RCP插件以从另一个非依赖插件加载类

时间:2012-10-18 15:51:58

标签: java osgi eclipse-rcp classloader gridgain

我有一组三个RCP插件:一个是我的主应用程序插件,另一个是计算集合,第三个是GridGain的包装器,其中包括从计算中创建类的实例插件。

主插件使用ExtensionPoint实例化从计算和GridGain插件实例化类,例如:

    IExtensionRegistry registry = Platform.getExtensionRegistry();

    IExtensionPoint providerExtensionPoint = registry.getExtensionPoint(EXT_CORE_DATA_PROVIDERS);
    IConfigurationElement[] providers = providerExtensionPoint.getConfigurationElements();

    List<DataProviderFactory> dataProviders = new ArrayList<DataProviderFactory>();
    for (IConfigurationElement member : providers) {
        try {
            Object obj = member.createExecutableExtension(K_CLASS);
            if (obj instanceof DataProviderFactoryFactory) {
                DataProviderFactoryFactory factory = (DataProviderFactoryFactory) obj;
                for (Object o : factory.createProviderFactories(this, holdingProperties())) {
                    dataProviders.add((DataProviderFactory) o);
                }
            }
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    return dataProviders;

因此与其他插件没有直接的依赖关系。

当GridGain必须从计算插件中实例化类的实例时,我的问题就出现了。由于GridGain插件没有直接依赖于计算插件,因此它的类加载过程没有看到那里的类,所以我得到了一个ClassNotFoundException。

我过去使用RCP buddy policies解决了类似问题,这似乎与您使用ORM时遇到的问题类似。但是,“注册”&#39;策略取决于定义类的插件(在我的情况下,计算插件)依赖于实例化它们的插件(GridGain插件)。在我的场景中,没有这种依赖。所以添加BuddyPolicy:注册到GridGain和RegisterBuddy:gridgain到计算插件不起作用。

我发现使GridGain插件从计算插件中解析类的唯一方法是将GridGain显式定义为依赖于计算。在我看来,这不应该是必要的,应该有一种方法可以让它成为一个软依赖,如果计算插件存在,GridGain可以从中实例化类。是否有另一种方法来模拟这种相互依赖性,以便我的类加载问题消失?

3 个答案:

答案 0 :(得分:1)

计算插件中应该有一些来自GridGain插件的依赖方式。如果您没有定义任何依赖项,GridGain将无法访问计算类。我可以想到这一点,使用通用接口创建另一个插件(基本插件),并使GridGain和Calculations依赖于基本插件。在计算插件中为您在基本插件中定义的接口公开声明性服务。

在GridGain插件中,使用osgi ServiceTracker等待计算插件中公开的服务。

答案 1 :(得分:1)

有两种安全的方法可以在不导入包的情况下从另一个包中实例化类。

在大多数情况下,您需要实现您知道的界面。对于这种情况,一个好的方法是为知道impl的bundle中的类创建一个工厂并发布它,例如使用OSGi服务。在工厂内部,然后可以使用new来实现类。

另一种方法是使用知道impl的bundle的类加载器。在这种情况下,您必须使用允许检索另一个包的类加载器的接口。然后你可以按名称加载类。

答案 2 :(得分:1)

你可以:

  1. 使计算插件的依赖性可选。

  2. 如果您事先知道包裹名称,请使用Import-Package代替Require-Bundle(再次,可能是可选的)。

  3. 使用DynamicImport-Package,但在大多数情况下应该避免这种情况。

相关问题