2015-11-02 51 views
0

我想用OSGI来完成某些东西,这些东西在Guice或Spring等依赖注入框架中非常直接。OSGI包可见服务实现

我想把服务实现类放到与服务接口相同的包中。这使我可以使用服务客户端不关心的包可见方法。

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类包可见的decleration或构造函数:

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; 
    } 
} 

把服务落实到另一个包,并试图建立良好的面向对象的封装需要太多的工作,如它映射的访问类的东西给调用者打包可见方法,我相信应该有另外一种方法。

+0

你试图破坏基于软件包的OSGI输出和输入。客户端总是需要导入接口的包,所以这个包必须在OSGi中导出。该实现不应该导出。所以即使你可以解决你的问题,你也应该总是使用单独的包来接口和impl。 –

回答

2

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

如果您的实现类与接口位于同一个包中,那么接口的每个客户端都会直接耦合到实现类。所以你可能只需要公开实现类并允许客户端直接实例化它。

OSGi允许真实分离合同,提供者和消费者。将合同和供应商合并到同一个软件包中会使其失败。 Guice和Spring将这些概念联系在一起的“直截了​​当”这一事实既不存在,也不存在。

+0

我同意尼尔。为什么要麻烦制作一个界面? –

+0

我相信,包可见类,即使包本身被导出也不能用于客户端,提供了一个简单的封装。并且在导出的包中隐藏方法没有简单的方法,只是为了从服务实现中访问而公开它们更容易。但我想这是OSGI的主要设计决定,所以我必须接受答案。 – b10y