在 OSGi 参考注释中动态设置目标 属性
Dynamically setting target property in OSGi Reference annotatation
阅读 article on 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%
在运行时自动计算(从设置文件读取)。
我是否应该只在 @Activate
/@Modified
注释方法中调用 getServiceReferences(Class<S> clazz, String filter)
以便在运行时获得正确的服务?
如果我没有明确使用 @Reference
并在 @Activate
/@Modified
注释方法中动态设置目标,那么 component.xml 是如何创建的?
我可以使用 @Designate
元类型注解让我的生活更简单吗?
即 article, you have read, is 7 year old and it is not clear to me which annotations it uses (yes, there are several). I'd suggest to ignore it. Today you better use Declarative Services (DS) 和标准 OSGi 注释。
简而言之,有两个重要部分:
- XML 文件在
/OSGI-INF
文件夹中提供/使用服务的包内
- 服务组件运行时 (SCR) - 一个在运行时检查其他包的包,如果它找到上述 XML 文件,则负责注册和连接服务。
虽然您可以手动编写 XML 文件,但它们通常由 Bnd or other build tools using Bnd (such us bnd-maven-plugin) 生成。这是在构建时完成的,当 Bnd 检查您的 类 注释并使用提供的信息生成 XML 文件时。因此在运行时根本不使用注释。
至于布线,当你有
@Reference(target="(type=pdf)")
Service service;
字段 service
将自动连接到 Service
服务的实例之一(是的,可以有多个实例),该实例在 OSGi 的服务注册表中注册并与目标过滤器匹配。这是由 SCR 在运行时完成的。您可以通过使用组件的 PID 重新配置组件来在运行时更改目标。您可以使用 Configuration Admin.
以编程方式或通过属性文件执行此操作
您提到的 @Designate
注释与另一个称为 Metatype 的 OSGi 规范有关。它允许您更好地定义配置字段的类型。 Here 您可以阅读有关如何将 Metatype 与 Declarative Services 1.3 一起使用的更多信息。
关于 OSGi 注释的另一个很好的信息来源是 here(忽略 Liferay 特定的)
为了反映您编辑过的问题,您有一些选择。一种是获取所有实例:
@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
地图按类型获取服务。另一个是重新配置您的组件。例如,如果你这样定义它
@Component(
configurationPid = "my.component"
)
public class MyComponent implements ... {
@Reference(target="(type=pdf)")
Service myService;
}
您可以通过 my.component.cfg
配置它,您可以在其中指定
myService.target=(type=somethingElse)
您可以使用配置管理以编程方式执行相同的操作API。
只需使用
@Reference
Service myService;
然后在运行时为您的组件创建配置并设置过滤器,如下所示:
myService.target=(mykey=1)
你可以这样做:
@Property(name = "myService.target", label = "My Service", description = "The target reference for the MyService, e.g. use target=(type=html) to bind to services by type.")
@Reference(name = "myService")
private Service myService;
然后您可以为您的组件创建配置文件 com.example.impl.MyComponent.config
:
myService.target="(type\=pdf)"
您还可以使用 Apache Felix Web 控制台 (http://localhost:8888/system/console/configMgr) 在运行时更改此值。
阅读 article on 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%
在运行时自动计算(从设置文件读取)。
我是否应该只在 @Activate
/@Modified
注释方法中调用 getServiceReferences(Class<S> clazz, String filter)
以便在运行时获得正确的服务?
如果我没有明确使用 @Reference
并在 @Activate
/@Modified
注释方法中动态设置目标,那么 component.xml 是如何创建的?
我可以使用 @Designate
元类型注解让我的生活更简单吗?
即 article, you have read, is 7 year old and it is not clear to me which annotations it uses (yes, there are several). I'd suggest to ignore it. Today you better use Declarative Services (DS) 和标准 OSGi 注释。
简而言之,有两个重要部分:
- XML 文件在
/OSGI-INF
文件夹中提供/使用服务的包内 - 服务组件运行时 (SCR) - 一个在运行时检查其他包的包,如果它找到上述 XML 文件,则负责注册和连接服务。
虽然您可以手动编写 XML 文件,但它们通常由 Bnd or other build tools using Bnd (such us bnd-maven-plugin) 生成。这是在构建时完成的,当 Bnd 检查您的 类 注释并使用提供的信息生成 XML 文件时。因此在运行时根本不使用注释。
至于布线,当你有
@Reference(target="(type=pdf)")
Service service;
字段 service
将自动连接到 Service
服务的实例之一(是的,可以有多个实例),该实例在 OSGi 的服务注册表中注册并与目标过滤器匹配。这是由 SCR 在运行时完成的。您可以通过使用组件的 PID 重新配置组件来在运行时更改目标。您可以使用 Configuration Admin.
您提到的 @Designate
注释与另一个称为 Metatype 的 OSGi 规范有关。它允许您更好地定义配置字段的类型。 Here 您可以阅读有关如何将 Metatype 与 Declarative Services 1.3 一起使用的更多信息。
关于 OSGi 注释的另一个很好的信息来源是 here(忽略 Liferay 特定的)
为了反映您编辑过的问题,您有一些选择。一种是获取所有实例:
@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
地图按类型获取服务。另一个是重新配置您的组件。例如,如果你这样定义它
@Component(
configurationPid = "my.component"
)
public class MyComponent implements ... {
@Reference(target="(type=pdf)")
Service myService;
}
您可以通过 my.component.cfg
配置它,您可以在其中指定
myService.target=(type=somethingElse)
您可以使用配置管理以编程方式执行相同的操作API。
只需使用
@Reference
Service myService;
然后在运行时为您的组件创建配置并设置过滤器,如下所示:
myService.target=(mykey=1)
你可以这样做:
@Property(name = "myService.target", label = "My Service", description = "The target reference for the MyService, e.g. use target=(type=html) to bind to services by type.")
@Reference(name = "myService")
private Service myService;
然后您可以为您的组件创建配置文件 com.example.impl.MyComponent.config
:
myService.target="(type\=pdf)"
您还可以使用 Apache Felix Web 控制台 (http://localhost:8888/system/console/configMgr) 在运行时更改此值。