【问题标题】:OSGI Package Visible Service ImplementationOSGI 包可见服务实现
【发布时间】:2015-11-02 08:43:39
【问题描述】:

我想用 OSGI 完成一些事情,这在 Guice 或 Spring 等依赖注入框架中非常简单。

我想把服务实现类和服务接口放在同一个包里。这使我能够使用与服务客户端无关的包可见方法。

Guice 实现这一点的方法很简单,让服务实现类包可见。服务接口:

package com.example.services;

public interface SomeService {

    void scanClasses(ServiceHelper helper);
}

以及实现:

package com.example.services;

// Package visible service implementation
class SomeServiceImpl implements SomeService {

    @Override
    public void scanClasses(ServiceHelper helper) {
        ClassLoader bundlesClassLoader = helper.getClassLoader();
        // do something with bundle's classes
    }

}

这是 ServiceHelper 类,它也有包可见的方法:

package com.example.services;

import org.osgi.framework.BundleContext;
import org.osgi.framework.wiring.BundleWiring;

public class ServiceHelper {
    private ClassLoader bundleClassLoader;

    public ServiceHelper(BundleContext bc) {
        this.bundleClassLoader = bc.getBundle().adapt(BundleWiring.class).getClassLoader();
    }

    // Package visible method to be called from SomeServiceImpl class
    ClassLoader getClassLoader() {
        return bundleClassLoader;
    }

}

但是 OSGI 不能用包可见声明或构造函数来实例化 ServiceImpl 类:

java.lang.IllegalAccessException:类 org.eclipse.equinox.internal.ds.model.ServiceComponent 无法访问带有修饰符“”的类 com.example.SomeServiceImpl 的成员

为了完成这个例子,这是服务客户端代码,它不应该受到设计的影响:

package com.example.serviceclient;

import org.osgi.framework.BundleContext;

import com.example.services.ServiceHelper;
import com.example.services.SomeService;

public class ServiceClientExample {

    private SomeService someService;

    public void activate(BundleContext bc) {
        someService.scanClasses(new ServiceHelper(bc));
    }

    public void setSomeService(SomeService service) {
        this.someService = service;
    }
}

将服务实现放到另一个包中,尝试构建好的面向对象的封装需要太多的工作,比如将包可见方法映射到调用者的访问器类,我相信应该有另一种方式。

【问题讨论】:

  • 您尝试做的事情会破坏基于包的 OSGI 导出和导入。客户端总是需要导入接口的包,所以这个包必须在 OSGi 中导出。不应导出实施。因此,即使您可以解决上述问题,您也应该始终为 interface 和 impl 使用单独的包。

标签: java osgi


【解决方案1】:

您正在使用 OSGi 声明式服务,它确实要求实现类是公共的并且具有公共的零参数构造函数。这是设计使然。您可以通过使用BundleActivator 并在代码中实例化组件来解决此问题,但是没有什么意义...

如果您的实现类与接口在同一个包中,则接口的每个客户端都直接与实现类耦合。所以你不妨把实现类公开,让客户端直接实例化。

OSGi 允许真正分离合同、提供者和消费者。将合同和提供者耦合到同一个包中会破坏这一点。 Guice 和 Spring 使将这些概念结合在一起变得“直截了当”的事实既不存在也不存在。

【讨论】:

  • 我相信即使包本身被导出也对客户端不可用的包可见类提供了一种简单的封装。并且没有简单的方法来隐藏导出包中的方法,将它们公开以便从服务实现中访问更容易。但我想这是 OSGI 的主要设计决定,所以我必须接受答案。
猜你喜欢
  • 2010-10-26
  • 1970-01-01
  • 2010-10-29
  • 2020-12-31
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 2011-12-02
  • 1970-01-01
相关资源
最近更新 更多