我有一个OSGi组件MyComponent.
该组件引用了一项服务MyService.现在MyService有几个实现MyServiceImpl1和MyServiceImpl2.MyComponent也有财产MyProperty.
现在我想要的是,只要MyProperty是1,就会MyComponent.MyService绑定MyServiceImpl1.如果我更改MyProperty为2,则MyComponent.MyService动态更新MyService绑定到"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 {
}
Run Code Online (Sandbox Code Playgroud)
该组件可能看起来像:
@Component
public class MyComponent {
@Reference(target="(impl=1)")
volatile MyService myService;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您将无法使用1或2的国旗,但你将不得不修改配置属性MyComponent的名称myService.target与另一个过滤器.(这与OSGi标准化注释一起显示.)
如果你坚持使用1或2(我们称之为select)的属性,MyComponent那么它就更精细了.首先,我们有满足的问题.MyComponent是否应该根据select属性impl 1满足,但只有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;
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,组件开始处理自己的依赖关系通常是一个坏主意.因此,我对你的现实世界情景感到好奇.
我发现总是非常尴尬和难以维护设计,其中组件对于他们引用的人是挑剔的.它有时是不可避免的,但在一般的解决方案中,MyServiceImpl2并且MyServiceImpl1决定注册或不基于某些条件更好地反映现实.
所以我有一个大问题是1或2属性在现实世界中反映出来了什么?这不能被建模为服务依赖吗?
(免责声明:代码未经过测试且无错误处理)
| 归档时间: |
|
| 查看次数: |
1729 次 |
| 最近记录: |