bundle 字段上的参考注释

Reference annotation on bundle field

我正在使用 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) 那里了解到 bindReference annotationunbind 方法的同步和并发有点棘手(尤其是在动态策略场景中)。特别是,通过注释引用服务的线程安全示例可能是:

@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),我如何实现线程安全?仅通过将参考定义为 "volatile"(如纲要建议的那样)?或者有一些棘手的部分会在应用程序中产生问题?

感谢您的回复

当您在字段上使用动态策略引用时,该字段必须是可变的。在您的示例中,每次 LogServices 集更改时,都会将一个新集合注入该字段。所以这将是安全的,因为如果您的代码迭代旧集合,则旧集合不会改变。当您的代码返回到日志字段时,它将看到新的集合。

所以您需要做的就是将字段声明为 volatile 并且不要将字段值存储在其他地方,因为只要绑定服务集发生变化,该字段就会更新为新集合。