OSGI 封装可视化服务实现
OSGI Package Visible Service Implementation
我想用 OSGI 完成一些事情,这在像 Guice 或 Spring 这样的依赖注入框架中非常简单。
我想将服务实现 class 放入与服务接口相同的包中。这使我能够使用与服务客户无关的包可见方法。
Guice 实现这一点的方法很简单,使服务实现 class 包可见。服务接口:
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 class,它也有包可见方法:
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 class 使用包可见 decleration 或构造函数:
java.lang.IllegalAccessException: Class org.eclipse.equinox.internal.ds.model.ServiceComponent can not access a member of class com.example.SomeServiceImpl with modifiers ""
为了完成示例,这是服务客户端代码,不应受设计影响:
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;
}
}
将服务实现放入另一个包中,并尝试构建良好的面向对象封装需要太多工作,比如访问器 class 将包可见方法映射到调用者,我相信应该有另一种方法.
您正在使用 OSGi 声明式服务,它确实需要实现 class 为 public 并具有 public 零参数构造函数。这是设计使然。您可以通过使用 BundleActivator
并在代码中实例化组件来解决此问题,但是没有什么意义...
如果您的实现 class 与接口在同一个包中,那么接口的每个客户端都直接耦合到实现 class。因此,您不妨只实现 class public 并允许客户端直接实例化它。
OSGi 允许真正分离契约、提供者和消费者。将合同和提供者耦合到同一个包中可以解决这个问题。 Guice 和 Spring 使 "straightforward" 将这些概念结合在一起的事实既不存在也不存在。
我想用 OSGI 完成一些事情,这在像 Guice 或 Spring 这样的依赖注入框架中非常简单。
我想将服务实现 class 放入与服务接口相同的包中。这使我能够使用与服务客户无关的包可见方法。
Guice 实现这一点的方法很简单,使服务实现 class 包可见。服务接口:
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 class,它也有包可见方法:
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 class 使用包可见 decleration 或构造函数:
java.lang.IllegalAccessException: Class org.eclipse.equinox.internal.ds.model.ServiceComponent can not access a member of class com.example.SomeServiceImpl with modifiers ""
为了完成示例,这是服务客户端代码,不应受设计影响:
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;
}
}
将服务实现放入另一个包中,并尝试构建良好的面向对象封装需要太多工作,比如访问器 class 将包可见方法映射到调用者,我相信应该有另一种方法.
您正在使用 OSGi 声明式服务,它确实需要实现 class 为 public 并具有 public 零参数构造函数。这是设计使然。您可以通过使用 BundleActivator
并在代码中实例化组件来解决此问题,但是没有什么意义...
如果您的实现 class 与接口在同一个包中,那么接口的每个客户端都直接耦合到实现 class。因此,您不妨只实现 class public 并允许客户端直接实例化它。
OSGi 允许真正分离契约、提供者和消费者。将合同和提供者耦合到同一个包中可以解决这个问题。 Guice 和 Spring 使 "straightforward" 将这些概念结合在一起的事实既不存在也不存在。