我开始越来越喜欢OSGi服务,并希望将更多的组件实现为服务。现在我正在寻找最佳实践,特别是UI组件。
对于听众关系,我使用白板模式,我个人认为这是最好的方法。但是,如果我想要的不仅仅是通知,我可以想到三个可能的解决方案。
想象下面的场景:
interface IDatabaseService {
EntityManager getEntityManager();
}
[1]白板模式-自带设置服务
我将创建一个新的服务接口:interface IDatabaseServiceConsumer {
setDatabaseService(IDatabaseService service);
}
并使用bindConsumer方法创建一个声明性IDatabaseService组件,如下所示
protected void bindConsumer(IDatabaseServiceConsumer consumer) {
consumer.setDatabaseService(this);
}
protected void unbindConsumer(IDatabaseServiceConsumer consumer) {
consumer.setDatabaseService(null);
}
这个方法假设只有一个IDatabaseService。
[Update]用法如下:
class MyUIClass ... {
private IDatabaseService dbService;
Consumer c = new IDatabaseServiceConsumer() {
setDatabaseService(IDatabaseService service) {
dbService = service;
}
}
Activator.registerService(IDatabaseServiceConsumer.class,c,null);
...
}
[2]
创建一个类似
的类公共类DatabaseEntryViewer扩展TableViewer
现在,我只是为我的IDatabaseService添加绑定/取消绑定方法,并添加一个component.xml和添加我的DatabaseEntryViewer。这种方法假设有一个无参数的构造函数,并且我通过OSGi-Service-Factory创建UI组件。
[3]经典方式:ServiceTracker
在Activator中注册静态ServiceTracker并访问它的经典方法。使用跟踪器的类必须处理动态的。
目前我更喜欢第一种方法,因为这种方法不会使对象创建变得复杂,并且可以将Activator从无休止的静态ServiceTrackers中节省出来。
我不得不同意@Neil Bartlett的观点,你的选项1是倒退的。你实际上是在使用观察者/可观察模式。
第二条是行不通的,因为在RCP中管理UI对象生命周期的方式不允许你做你想做的事情。小部件必须作为某种视图容器(ViewPart、Dialog等)初始化的一部分创建。这个视图部分通常通过Workbench/插件机制进行配置和管理。你应该配合它,而不是反对它。
第三个是一个简单的选择,不一定是最好的,但很简单。
如果您使用Spring DM,那么您可以轻松地完成第2点。它提供了一种将服务bean注入UI视图、页面等的方法。您使用spring工厂来创建视图(如在plugin.xml中定义的那样),视图通过spring配置进行配置,该配置能够将您的服务注入到bean中。
您还可以将SpringExtensionFactory类使用的技术与DI结合起来完成相同的任务,而无需引入另一项技术。我自己还没有尝试过,所以我不能评论它的难度,尽管如果我还没有使用Spring DM,我会尝试这样做来弥合RCP和OSGi之间的差距。