我正在使用 OSGi 开发应用程序。看里面 OSGi compendium 6.0 (section 112.8.1) 我遇到过声明式服务;特别是我看了以下段落:
For a field, the defaults for the Reference annotation are:
- The name of the bind method or field is used for the name of the reference.
- 1:1 cardinality if the field is not a collection. 0..n cardinality if the field is a collection.
- Static reluctant policy if the field is not declared volatile. Dynamic reluctant policy if the field is declared volatile
- The requested service is the type of the field.
For example:
@Reference volatile Collection<LogService> log;
现在,我从 Neil Bartlett's OSGi in practice (section 11.10.2) 读取Reference annotation
的bind 和unbind 方法的同步和并发有点棘手(尤其是在动态策略场景中)。特别是,通过注释引用服务的线程安全示例可能是:
@Component( provide = MailboxListener.class, properties = { "service.ranking = 10"})
public class LogMailboxListener implements MailboxListener {
private final AtomicReference<Log> logRef = newAtomicReference <Log> () ;
public void messagesArrived ( String mboxName, Mailbox mbox, long [ ] ids ) {
Log log = logRef.get();
if (log != null )
log.log(Log.INFO, ids.length + "message(s) arrived in mailbox " + mboxName, null);
else
System.err.println("No log available!");
}
@Reference( service = Log.class, dynamic = true, optional = true )
public void setLog(Log log) {
logRef.set(log);
}
public void unsetLog(Log log) {
logRef.compareAndSet(log, null);
}
}
我想我从书中领会了为什么动态策略需要从多线程场景进行这种调整。我的问题是:如果引用注释在一个字段上(声明式服务 1.3),我如何实现线程安全?仅通过将引用定义为“易变”(如纲要建议的那样)?或者有一些棘手的部分会在应用程序中产生问题?
谢谢你的回复
最佳答案
当您在字段上使用动态策略引用时,该字段必须是可变的。在您的示例中,每次 LogServices 集更改时,都会将一个新集合注入(inject)该字段。所以这将是安全的,因为如果您的代码迭代旧集合,则旧集合不会改变。当您的代码返回到日志字段时,它将看到新的集合。
因此,您需要做的就是将字段声明为 volatile,并且不要将字段值存储在其他地方,因为只要绑定(bind)服务集发生变化,该字段就会更新为新集合。
关于java - bundle 字段上的引用注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40175076/