我们如何确保在activate()
调用之前注入所有依赖项?
private IMyDependency aInstance, bInstance, cInstance;
public void setDependency(IMyDependency depInstance) {
Bundle depBundle = FrameworkUtil.getBundle(depInstance.getClass());
logger.debug("Dependency {} from bundle {} retrieved", depInstance, depBundle.getSymbolicName());
if (A_BUNDLE_NAME.equals(depBundle.getSymbolicName())) {
aInstance = depInstance;
} else if (B_BUNDLE_NAME.equals(depBundle.getSymbolicName())) {
bInstance = depInstance;
} else if (C_BUNDLE_NAME.equals(depBundle.getSymbolicName())) {
cInstance = depInstance;
} else {
logger.error("Dependency {} from unknown bundle {}", depInstance, depBundle);
}
}
public void activate() {
Preconditions.checkNotNull(aInstance);
Preconditions.checkNotNull(bInstance);
Preconditions.checkNotNull(cInstance);
//...
}
有多个IMyDependency实例,依赖基数为0..n
。
问题是,setDependency()
有时在activate()
方法之后调用。解决方法是更改依赖包的启动级别,但我们真的不想触摸配置。
答案 0 :(得分:2)
现在对于带有注释的整个组件:
@Component public class MyComponent {
@Reference(target="(dependencyType=A)") IMyDependency aInstance;
@Reference(target="(dependencyType=B)") IMyDependency bInstance;
@Reference(target="(dependencyType=C)") IMyDependency cInstance;
@Activate public void activate() {
// all guaranteed set
}
}
实例组件:
@Component public class MyDependency implements IMyDependency {
...
}
您应该使用configuration创建3个实例。
答案 1 :(得分:1)
通过Balazs'评论,我能够将0..n
个依赖项更改为3个显式1..1
个依赖项:
<reference bind="setDependencyA" cardinality="1..1" interface="com.example.IMyDependency" name="DepA" policy="static" target="(dependencyType=A)"/>
<reference bind="setDependencyB" cardinality="1..1" interface="com.example.IMyDependency" name="DepB" policy="static" target="(dependencyType=B)"/>
<reference bind="setDependencyC" cardinality="1..1" interface="com.example.IMyDependency" name="DepC" policy="static" target="(dependencyType=C)"/>
依赖类:
public void setDependencyA(IMyDependency depInstance) {
aInstance = depInstance;
}
public void setDependencyB(IMyDependency depInstance) {
bInstance = depInstance;
}
public void setDependencyC(IMyDependency depInstance) {
cInstance = depInstance;
}
我还必须更改依赖项的激活(不幸的是,依赖项不使用DS):
@Override
public void start(BundleContext context) throws Exception {
Hashtable<String, String> props = new Hashtable<>();
props.put("dependencyType", "A");
srvReg = context.registerService(IMyDependency.class.getName(), myInstance, props);
}
答案 2 :(得分:1)
我想你想要的是一种插件系统。所以你知道界面,但是你不知道有多少个impls,但是你想确保在加载之前加载所有的impls。
在OSGi中这并不容易。事实上,额外的服务可能会在运行时出现。因此,一种解决方案是简单地适应服务的所有变化。在某些情况下,这还不够。
例如,我有一个案例,我想为我的应用程序提供安全插件。我的软件包在没有安全插件的情况下启动是不可接受的,但它应该是可配置的。
所以我做的是使用OSGi属性为每个插件命名,在插件机制中我允许列出要在配置pid中加载的所有插件的名称。该机制确保主应用程序仅在所有命名插件都存在时启动。不幸的是,这种机制并没有内置到DS中,但您可以使用bind和unbind方法实现它。
答案 3 :(得分:0)
普通的OSGi在管理依赖关系方面非常坚定。你应该明确你的依赖链。通过实施智能服务跟踪器可以延长初始化时间,直到所有依赖项都可用为止,您可以获得更多动态。但是,我建议您使用声明性服务来避免旧式依赖注入。