我几周前开始使用OSGi,对DS有疑问。
假设我有2个捆绑包,捆绑包A和捆绑包B.两者都通过DS / BND注释注册服务。
Bundle A引用了bundle B的服务,并实现了所需的set和unset函数。
@Reference(dynamic = true, optional = true)
void setConnector(IDataBaseConnect connector) {
this.connector = connector;
doSomeStuff();
sysout("Connector SET"); <---- NOT called when doSomeStuff runs into an error
}
当doSomeStuff()遇到错误
时,永远不会调用它void unsetConnector(IDataBaseConnect connector){
this.connector = null
}
正如你所看到的,我希望引用动态和可选,但是,如果连接器服务可用,我想在包A中做一些事情。
在我的案例中,Bundle B具有一些基本的数据库功能。 Bundle A使用它来从数据库中读取一些数据并将其缓存在一些java对象中。其他服务将使用此数据。
但是,我对这种方法有疑问。如果我的数据库服务引用设置为Bundle A,我在setConnector函数中启动我的数据库操作。只要一切顺利,我都没有问题。参考设置,数据变红,一切都很好。但是如果DB-Service遇到异常(是的,它被捕获并处理),DS似乎会忘记&#34;关于集合参考,当我停止服务时它永远不会被删除。
我想我不应该调用setConnector函数中的任何函数,但是如果是这样的话,我将如何实现一个仅在设置新引用时调用的方法?
答案 0 :(得分:1)
在极少数情况下应使用动态和可选参考。到目前为止我既没有使用动态也没有可选参考,尽管我实现了很多组件。在数据库连接的情况下,还有其他问题:
我建议你应该使用非动态的非可选引用,并将 doSomeStuff()逻辑放入你的activate方法中。在这种情况下,您可以确保在业务逻辑运行时该引用可用。
答案 1 :(得分:1)
如果doSomeStuff()
抛出异常然后从绑定方法setConnector
传播出来,则DS将假定您的绑定方法已损坏,并且您的组件未能接受绑定服务。然后,DS会将服务视为未绑定到组件,因此不会调用该服务的unbind方法。
您需要在bind方法中处理来自doSomeStuff()
的任何异常。例如:
@Reference(dynamic = true, optional = true)
void setConnector(IDataBaseConnect connector) {
this.connector = connector;
try {
doSomeStuff();
} catch (Exception e) {
// handle e but don't let it propagate out of this bind method
}
sysout("Connector SET");
}