在OSGi中,类ServiceTracker
定义了两个类型参数:
S
- 正在跟踪的服务类型。T
- 跟踪对象的类型。他们两个有什么区别?
答案 0 :(得分:3)
在几乎所有情况下,我都使用服务跟踪器,我需要做一些与被跟踪对象相关的内务处理。当被跟踪的物体消失时,该管家信息应该被垃圾收集。
例如,您跟踪WhiteboardListeners
。但是,您希望跟踪它们用于回调的时间长度,如果它们使用太多时间则拒绝它们服务。所以我们创建一个包装器:
public class Example {
interface Whiteboard {
void visit();
}
static class Wrapper {
Whiteboard whiteboard;
AtomicLong averageTime = new AtomicLong();
public Wrapper(Whiteboard whiteboard) {
this.whiteboard = whiteboard;
}
void visit() {
if (averageTime.get() < 100) {
long start = System.currentTimeMillis();
whiteboard.visit();
long time = System.currentTimeMillis() - start;
averageTime.getAndUpdate(v -> (99 * v + time) / 100);
} else
averageTime.getAndUpdate(v -> (99 * v) / 100);
}
}
ServiceTracker<Whiteboard, Wrapper> tracker;
@Activate
void activate(BundleContext context) {
tracker = new ServiceTracker<Whiteboard, Wrapper>(context,
Whiteboard.class, null) {
@Override
public Wrapper addingService(
ServiceReference<Whiteboard> reference) {
return new Wrapper(context.getService(reference));
}
@Override
public void removedService(ServiceReference<Whiteboard> reference,
Wrapper service) {
context.ungetService(reference);
}
};
tracker.open();
}
void visit() {
tracker.getTracked().values().forEach(wrapper -> wrapper.visit());
}
}
我现在很少使用服务跟踪器,因为声明服务在大多数情况下更容易完成工作。但是,当我使用服务跟踪器时,我很少有S==T
。
答案 1 :(得分:1)
跟踪对象允许您在再次删除服务时进行任何必要的内务管理。
作为示例,请参阅trackers in pax-jdbc。在这种情况下,我们需要两个服务。 PooledDataSourceFactoryTracker将为DataSourceFactory启动另一个跟踪器。该第二跟踪器是第一跟踪器的跟踪对象。当再次删除PooledDataSourceFactory时,其他DataSourceFactory跟踪器也会关闭。
此方法允许跟踪多个服务或执行其他服务删除,而无需处理线程。
请注意,即使采用这种方法,服务跟踪器也很难正确使用。在大多数情况下,最好从一开始就使用声明式服务等框架。
答案 2 :(得分:1)
T
可让您跟踪与该服务类型S
不同的类型。例如,您可以将服务S
包装在T
类型的对象中。对于大多数用例,S
和T
都是相同的。但是有一些用例T != S
。