我是第一次学习 OSGi 和声明性服务,无法弄清楚为什么我的
@Reference
字段的“更新”方法没有被调用。我使用的是菲利克斯 7.0.5。我使用 org.apache.felix:maven-bundle-plugin: 使用 Maven 构建了三个捆绑包
osgi.api
:包含单个界面 ITask
osgi.taskserviceds
:包含单个类 TaskRunnerDs
和 @Reference
字段osgi.plugin1
:包含实现 Plugin1DsTask
接口的类 ITask
。TaskRunnerDs
中的参考字段显然正在使用Plugin1DsTask
进行更新,因为我在类中添加了一个执行器来定期检查内容并将其打印出来。但是,我在“更新”属性中指示的方法从未被调用。我找不到任何表明存在问题的内容。我看到的唯一可能的问题是 osgi.plugin1
捆绑包首先启动。然而,我使用 ServiceTracker
完成了同样的练习,这不是问题。我做错了什么?
菲利克斯的输出:
$ java -jar bin/felix.jar
Starting bundle: com.osgi.api
Done starting bundle: com.osgi.api
Starting bundle: com.osgi.plugin1
Done starting bundle: com.osgi.plugin1
Starting bundle: com.osgi.taskserviceds
Done starting bundle: com.osgi.taskserviceds
*** Plugin1DsTask created
*** TaskRunnerDs created
*** TaskRunnerDs activated
____________________________
Welcome to Apache Felix Gogo
g!
*** TaskRunnerDs running - tasks: [com.osgi.plugin1.activator.Plugin1DsTask@bed2ccd]
*** TaskRunnerDs running - tasks: [com.osgi.plugin1.activator.Plugin1DsTask@bed2ccd]
*** TaskRunnerDs running - tasks: [com.osgi.plugin1.activator.Plugin1DsTask@bed2ccd]
*** TaskRunnerDs running - tasks: [com.osgi.plugin1.activator.Plugin1DsTask@bed2ccd]
... <remaining output omitted> ...
g! lb 17:39:56
START LEVEL 1
ID|State |Level|Name
0|Active | 0|System Bundle (7.0.5)|7.0.5
1|Active | 1|jansi (1.18.0)|1.18.0
2|Active | 1|JLine Bundle (3.13.2)|3.13.2
3|Active | 1|Apache Felix Bundle Repository (2.0.10)|2.0.10
4|Active | 1|Apache Felix Gogo Command (1.1.2)|1.1.2
5|Active | 1|Apache Felix Gogo JLine Shell (1.1.8)|1.1.8
6|Active | 1|Apache Felix Gogo Runtime (1.1.4)|1.1.4
7|Active | 1|Apache Felix Declarative Services (2.2.6)|2.2.6
8|Active | 1|org.osgi:org.osgi.namespace.extender (1.0.1.201505202024)|1.0.1.201505202024
9|Active | 1|org.osgi:org.osgi.service.component (1.5.1.202212101352)|1.5.1.202212101352
10|Active | 1|org.osgi:org.osgi.service.component.annotations (1.5.1.202212101352)|1.5.1.202212101352
11|Active | 1|org.osgi:org.osgi.util.function (1.0.0.201505202023)|1.0.0.201505202023
12|Active | 1|org.osgi:org.osgi.util.promise (1.0.0.201505202023)|1.0.0.201505202023
13|Active | 1|osgi.api (1.0.0)|1.0.0
14|Active | 1|osgi.plugin1 (1.0.0)|1.0.0
15|Active | 1|osgi.taskserviceds (1.0.0)|1.0.0
ITask.java:
package com.osgi.task.api;
import java.util.concurrent.TimeUnit;
public interface ITask extends Runnable {
String getName();
int getInterval();
TimeUnit getIntervalUnit();
}
TaskRunnerDs.java
package com.osgi.taskservice.ds;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import com.osgi.task.api.ITask;
@Component
public class TaskRunnerDs {
@Reference(updated = "updatedTasks", policy = ReferencePolicy.DYNAMIC, cardinality = ReferenceCardinality.AT_LEAST_ONE)
public volatile List<ITask> fTasks;
public TaskRunnerDs() {
System.out.println("*** TaskRunnerDs created");
// for debugging
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleWithFixedDelay(() -> System.out.println("*** TaskRunnerDs running - tasks: " + fTasks),
1,
1,
TimeUnit.SECONDS);
}
@Activate
public void activate() {
System.out.println("*** TaskRunnerDs activated");
}
public void updatedTasks() {
System.out.println("*** Change detected to task list - new list:");
for (ITask task : fTasks) {
System.out.println("Task: " + task.getName() + " - " + task.getInterval() + " " + task.getIntervalUnit());
}
}
}
Plugin1DsTask.java:
package com.osgi.plugin1.activator;
import java.util.concurrent.TimeUnit;
import org.osgi.service.component.annotations.Component;
import com.osgi.task.api.ITask;
@Component
public final class Plugin1DsTask implements ITask {
public Plugin1DsTask() {
System.out.println("*** Plugin1DsTask created");
}
@Override
public String getName() {
return getClass().getSimpleName();
}
@Override
public int getInterval() {
return 2;
}
@Override
public TimeUnit getIntervalUnit() {
return TimeUnit.SECONDS;
}
@Override
public void run() {
System.out.println("Running task: " + getName());
}
}
看起来这可能是 Apache Felix DS 中的一个错误。您应该提交错误。
您对
@Reference
的使用是一个“混合”用例,因为它使用字段注入进行绑定/解除绑定,但使用方法注入进行更新。 Felix DS 可能没有正确处理此用例。