在 OSGi 中,被跟踪的服务类型和被跟踪对象的类型有什么区别
In OSGi, what is the difference between type of service being tracked and type of the tracked object
在 OSGi 中 class ServiceTracker
定义了两个类型参数:
S
- 被跟踪的服务类型。
T
- 跟踪对象的类型。
两者有什么区别?
被跟踪的对象允许您在再次删除服务时进行任何必要的内务处理。
示例见 trackers in pax-jdbc。在这种情况下,我们需要两个服务。 PooledDataSourceFactoryTracker 将为 DataSourceFactory 启动另一个跟踪器。第二个跟踪器是第一个跟踪器的跟踪对象。当再次删除 PooledDataSourceFactory 时,另一个 DataSourceFactory 跟踪器也将关闭。
这种方法允许跟踪多个服务或在服务删除时进行其他内务处理,而无需处理线程。
请注意,即使使用这种方法,服务跟踪器也很难正确使用。在大多数情况下,最好从一开始就使用声明式服务等框架。
T
允许您跟踪与该服务类型 S
不同的类型。例如,您可以将服务 S
包装在类型 T
的对象中。对于大多数用例,S
和 T
是相同的。但是有些用例 T != S
.
在几乎所有情况下,我都使用服务跟踪器,我需要做一些与跟踪对象相关的内务处理。当被跟踪的对象消失时,该管理信息应该被垃圾收集。
例如,您跟踪 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());
}
}
我现在很少使用 Service Tracker,因为声明式服务在大多数情况下更容易完成这项工作。但是,当我使用 Service Tracker 时,我很少遇到 S==T
.
在 OSGi 中 class ServiceTracker
定义了两个类型参数:
S
- 被跟踪的服务类型。T
- 跟踪对象的类型。
两者有什么区别?
被跟踪的对象允许您在再次删除服务时进行任何必要的内务处理。
示例见 trackers in pax-jdbc。在这种情况下,我们需要两个服务。 PooledDataSourceFactoryTracker 将为 DataSourceFactory 启动另一个跟踪器。第二个跟踪器是第一个跟踪器的跟踪对象。当再次删除 PooledDataSourceFactory 时,另一个 DataSourceFactory 跟踪器也将关闭。
这种方法允许跟踪多个服务或在服务删除时进行其他内务处理,而无需处理线程。
请注意,即使使用这种方法,服务跟踪器也很难正确使用。在大多数情况下,最好从一开始就使用声明式服务等框架。
T
允许您跟踪与该服务类型 S
不同的类型。例如,您可以将服务 S
包装在类型 T
的对象中。对于大多数用例,S
和 T
是相同的。但是有些用例 T != S
.
在几乎所有情况下,我都使用服务跟踪器,我需要做一些与跟踪对象相关的内务处理。当被跟踪的对象消失时,该管理信息应该被垃圾收集。
例如,您跟踪 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());
}
}
我现在很少使用 Service Tracker,因为声明式服务在大多数情况下更容易完成这项工作。但是,当我使用 Service Tracker 时,我很少遇到 S==T
.