我有一个 OSGi 组件 MyComponent
.
该组件引用了服务 MyService
.现在MyService
有几个实现 MyServiceImpl1
和 MyServiceImpl2
. MyComponent
还有房产MyProperty
.
现在我想要的是每当MyProperty
是 1,MyComponent.MyService
绑定(bind)到 MyServiceImpl1
.如果我改变 MyProperty
到 2, MyComponent.MyService
动态更新MyService
绑定(bind)到`MyServiceImpl2。
我如何实现这一目标?作为引用,我使用的是 Apache Felix 容器,并且希望避免使用较低级别的 OSGi api。
最佳答案
配置依赖项的最简单方法是使用“.target”属性。这要求实现注册一个识别属性,比如说 impl=1
.和 impl=2
.
@Component(property="impl=1")
public class MyServiceImpl1 implements MyService {
}
@Component(property="impl=2")
public class MyServiceImpl2 implements MyService {
}
然后该组件可能如下所示:
@Component
public class MyComponent {
@Reference(target="(impl=1)")
volatile MyService myService;
}
在这种情况下,您将无法使用 1 或 2 作为标志,但您必须修改
MyComponent
的配置属性。名称为 myService.target
与另一个过滤器。 (这与 OSGi 标准化注释一起显示。)如果您坚持
select
的属性为 1 或 2(我们称之为 MyComponent
)然后它更详细。首先,我们有满足的问题。根据选择属性 impl 1 需要 MyComponent 但只有 2 可用时是否应该满足?如果没问题,那么以下更复杂的解决方案应该可以工作@Designate( ocd=Config.class )
@Component( property = "select=1" )
public class MyComponent {
static Class<?> types [] = {
MyServiceImpl1.class,
MyServiceImpl2.class,
};
@interface Config {
int select() default 1;
}
@Reference(target="(|(impl=1)(impl=2))")
volatile List<MyService> candidates;
volatile MyService selected;
@Activate
@Modify
void changed( Config config ) {
Class<?> type = types[config.select()];
Optional<MyService> service = candidates.
stream().
filter( type::isInstance ).
findFirst();
this.service = service.isPresent() ? service.get() : null;
}
}
正如您所看到的,组件开始处理自己的依赖项通常是一个坏主意。因此,我对您的真实世界场景感到好奇。
我发现在组件对引用对象挑剔的情况下,维护设计总是非常尴尬和困难。有时这是不可避免的,但在一般解决方案中,
MyServiceImpl2
和 MyServiceImpl1
根据一些条件决定是否注册更好地反射(reflect)现实。所以我最大的问题是 1 或 2 属性在现实世界中反射(reflect)了什么?这不能被建模为服务依赖吗?
(免责声明:代码未经测试且没有错误处理)
关于osgi - 如何动态更新 OSGi 组件中的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37940008/