阅读 article 之后在 Reference target (和相应的属性),我仍然不明白如何在 target
时检索服务在运行时设置(通常目标和属性在编译时设置并由 SCR 在运行时评估)。
假设有三个服务实现定义了 @Property(name="type", value="csv")
, @Property(name="type", value="xls")
和 @Property(name="type", value="pdf")
, 分别。
一个消费者:
//@Reference(target="(type=%runtime_variable%)")
Service service;
注意 %runtime_variable%
在运行时自动评估(从设置文件中读取)。
我应该调用getServiceReferences(Class<S> clazz, String filter)
吗?在@Activate
/@Modified
注释方法以便在运行时获得正确的服务?
如果我不显式使用 @Reference
,如何创建 component.xml并在 @Activate
中动态设置目标/@Modified
注释方法?
我可以使用 @Designate
吗?元类型注解让我的生活更简单?
最佳答案
那个article ,你读过,是 7 岁,我不清楚它使用了哪些注释(是的,有几个)。我建议忽略它。今天你最好使用Declarative Services (DS)以及标准的 OSGi 注释。
简而言之,有两个重要部分:
/OSGI-INF
文件夹中的 XML 文件提供/消费服务- 服务组件运行时 (SCR) - 一个在运行时检查其他 bundle 的 bundle ,如果它找到上述 XML 文件,则负责注册和连接服务。
虽然您可以手动编写 XML 文件,但它们通常由 Bnd 生成或其他使用 Bnd 的构建工具(例如我们 bnd-maven-plugin )。这是在构建时完成的,当时 Bnd 检查您的类的注释并使用提供的信息来生成 XML 文件。因此在运行时根本不使用注释。
至于布线,当你有
@Reference(target="(type=pdf)")
Service service;
字段 service
将自动连接到在 OSGi 的服务注册表中注册的与目标匹配的 Service
服务实例之一(是的,可以有多个)筛选。这是由 SCR 在运行时完成的。您可以通过使用组件的 PID 重新配置组件来在运行时更改目标。您可以使用 Configuration Admin 以编程方式或通过属性文件执行此操作.
您提到的@Designate
注释与另一个称为Metatype 的OSGi 规范有关。它允许您更好地定义配置字段的类型。 Here您可以阅读有关如何将 Metatype 与 Declarative Services 1.3 一起使用的更多信息。
关于 OSGi 注释的另一个很好的信息来源是 here (忽略 Liferay 特定的)
为了反射(reflect)您编辑的问题,您有一些选择。一种是获取所有实例:
@Reference(
cardinality = ReferenceCardinality.MULTIPLE,
policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY
)
protected void setService(Service service, Map<String, Object> properties) {
String type = MapUtil.getString(properties, "type");
_services.put(type, service);
}
然后你可以从 _services
map 按类型获取你的服务。另一个是重新配置您的组件。例如,如果你这样定义它
@Component(
configurationPid = "my.component"
)
public class MyComponent implements ... {
@Reference(target="(type=pdf)")
Service myService;
}
你可以通过 my.component.cfg
在你指定的地方配置它
myService.target=(type=somethingElse)
您可以使用配置管理 API 以编程方式执行相同的操作。
关于java - 在 OSGi 引用注释中动态设置目标属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47393876/