在OSGi参考注释中动态设置目标属性 [英] Dynamically setting target property in OSGi Reference annotatation
问题描述
在阅读文章之后在参考目标(以及相应的属性),当在运行时设置了target
时,我仍然不了解如何检索服务(通常目标和属性是在编译时设置,并在运行时由SCR进行评估.
After reading an article on Reference target (and corresponding properties), I still don't understand how to retrieve a service, when target
is set at runtime (typically target and properties are set at compile time and evaluated by SCR at runtime).
假设有三种服务实现分别定义了@Property(name="type", value="csv")
,@Property(name="type", value="xls")
和@Property(name="type", value="pdf")
.
Let's say there are three service implementations defining@Property(name="type", value="csv")
, @Property(name="type", value="xls")
and @Property(name="type", value="pdf")
, respectively.
一名消费者:
//@Reference(target="(type=%runtime_variable%)")
Service service;
注意 %runtime_variable%
在运行时自动评估(从设置文件中读取).
NOTE %runtime_variable%
is automatically evaluated at runtime (read from a settings file).
我应该只在@Activate
/@Modified
带注释的方法中调用getServiceReferences(Class<S> clazz, String filter)
以便在运行时获得正确的服务吗?
Should I just call getServiceReferences(Class<S> clazz, String filter)
in the @Activate
/@Modified
annotated method in order to get the right service at runtime?
如果我不显式使用@Reference
并在@Activate
/@Modified
带注释的方法中动态设置目标,那么如何创建component.xml?
How is the component.xml created, if I don't explicitly use @Reference
and dynamically set the target in the @Activate
/@Modified
annotated method?
And can I use the@Designate
metatype annotation to make my life simpler here?
推荐答案
该声明性服务(DS)和标准的OSGi注释
That 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) and the standard OSGi annotations.
简而言之,有2个重要部分:
In short there are 2 important pieces:
-
捆绑包内提供/使用服务的
- XML文件
- 服务组件运行时(SCR)-一个在运行时检查其他捆绑软件的捆绑软件,如果找到上述XML文件,则负责注册和连接服务.
/OSGI-INF
文件夹中的- XML files in
/OSGI-INF
folder inside the bundles providing / consuming services - Service Component Runtime (SCR) - a bundle that inspects other bundles at runtime and if it finds the above XML files, takes care of registering and wiring the services.
虽然您可以手工编写XML文件,但是它们通常是由 Bnd 或其他构建工具生成的使用Bnd(例如 bnd-maven-plugin ).当Bnd检查您的类中是否有注释并使用提供的信息来生成XML文件时,将在构建时完成此操作.因此,注释在运行时根本不会使用.
While you can write the XML files by hand, they are typically generated by Bnd or other build tools using Bnd (such us bnd-maven-plugin). This is done at build time when Bnd inspects your classes for annotations and uses the information provided to generate the XML files. Thus the annotations are not used at all at runtime.
关于接线,当您拥有
@Reference(target="(type=pdf)")
Service service;
字段service
将自动连接到在OSGi的服务注册表中注册的与目标过滤器匹配的Service
服务的一个实例(是的,可以有多个).这是在运行时由SCR完成的.您可以在运行时通过使用组件的PID重新配置组件来更改目标.您可以通过程序或使用配置管理器 a>.
The field service
will be automatically wired to one of the instances (yes there can be more than one) of Service
service registered in OSGi's service registry that matches the target filter. This is done at runtime by SCR. You can change the target at runtime by reconfiguring your component using its PID. You can do that programmatically or via properties files using Configuration Admin.
您提到的@Designate
批注与另一个名为Metatype的OSGi规范有关.它使您可以更好地定义配置字段的类型. 在这里,您可以阅读有关如何将Metatype与声明式服务1.3.
The @Designate
annotation you mentioned relates to another OSGi specification called Metatype. It allows you to better define the types of the configuration fields. Here you can read more about how to use Metatype together with Declarative Services 1.3.
Another good source of information regarding OSGi annotations is here (ignore the Liferay specific ones)
要反映您已编辑的问题,您可以选择一些方法.一种是获取所有实例:
To reflect your edited question, you have some options. One is to get all instances:
@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
地图获得服务.另一个是重新配置您的组件.例如,如果您这样定义它
Then you can get your service from _services
map by type. Another is reconfigure your component. For example if you define it like this
@Component(
configurationPid = "my.component"
)
public class MyComponent implements ... {
@Reference(target="(type=pdf)")
Service myService;
}
您可以通过my.component.cfg
在其中指定
myService.target=(type=somethingElse)
您可以使用Configuration Admin API以编程方式执行相同的操作.
You can do the same programmatically using the Configuration Admin API.
这篇关于在OSGi参考注释中动态设置目标属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!