OSGi松耦合最佳实践

pto*_*mli 5 java osgi design-patterns

我想知道什么被认为是将应用程序代码与框架代码分离的最佳实践或模式,特别是关于OSGi.

我将使用Felix SCR页面中示例

示例服务是比较器

package sample.service;
import java.util.Comparator;
public class SampleComparator implements Comparator
{
    public int compare( Object o1, Object o2 )
    {
        return o1.equals( o2 ) ? 0 : -1;
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码没有框架管道,它集中和简洁.在使用OSGi时,将其提供给应用程序涉及将其注册到服务注册表.如链接的Felix页面所述,一种方法是使用服务组件运行时.

// OSGI-INF/sample.xml
<?xml version="1.0" encoding="UTF-8"?>
<component name="sample.component" immediate="true">
  <implementation class="sample.service.SampleComparator" />
  <property name="service.description" value="Sample Comparator Service" />
  <property name="service.vendor" value="Apache Software Foundation" />
  <service>
    <provide interface="java.util.Comparator" />
  </service>
</component>
Run Code Online (Sandbox Code Playgroud)

Service-Component: OSGI-INF/sample.xml
Run Code Online (Sandbox Code Playgroud)

一切都很好,可爱,我的服务实现根本没有与OSGI的耦合.

现在我想使用该服务......

package sample.consumer;
import java.util.Comparator;
public class Consumer {
    public void doCompare(Object o1, Object o2) {
        Comparator c = ...;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用SCR查找策略我需要添加仅框架方法:

protected void activate(ComponentContext context) {
    Comparator c = ( Comparator ) context.locateService( "sample.component" );
}
Run Code Online (Sandbox Code Playgroud)

使用SCR事件策略我还需要添加仅框架方法:

protected void bindComparator(Comparator c) {
    this.c = c;
}

protected void unbindComparator(Comparator c) {
    this.c = null;
}
Run Code Online (Sandbox Code Playgroud)

虽然我认为很可能你最终会在类中重复使用相当数量的这类代码,这会使得过滤噪声更大,但两者都不是非常繁琐.

我可以看到的一个可能的解决方案是使用OSGi特定类来通过更传统的方式和框架在消费者之间进行调解.

package sample.internal;
public class OsgiDependencyInjector {
    private Consumer consumer;
    protected void bindComparator(Comparator c) {
        this.consumer.setComparator(c);
    }

    protected void unbindComparator(Comparator c) {
        this.consumer.setComparator(null);
    }
}
Run Code Online (Sandbox Code Playgroud)

虽然我不确定你如何在SCR配置中安排这个.

还有org.apache.felix.scr.annotations,但这意味着只有你使用maven-scr-plugin构建它才会起作用.真的不是那么糟糕,而且,AFAICT,它们不会产生运行时影响.

所以,现在你已经阅读了所有这些内容,你有什么建议是消费OSGi提供服务的最好方法,而不用框架代码"污染"应用程序代码?

Pet*_*ens 3

1)我不认为绑定方法会污染你的代码,它们只是bean设置器(你也可以将它们称为setXXX,更传统)。您还需要这些来进行单元测试。

\n\n

2)如果你使用bnd(在maven、ant、bndtools、eclipse插件等中)那么你也可以使用bnd注释。然后 bnd 会自动为你创建(总是可怕的)xml。

\n\n
package sample.service;\nimport java.util.Comparator;\nimport aQute.bnd.annotations.component.*;\n\n@Component\npublic class SampleComparator implements Comparator {\n    public int compare( Object o1, Object o2 ) {\n        return o1.equals( o2 ) ? 0 : -1;\n    }\n}\n\n@Component\nclass Consumer {\n    Comparator comparator;\n\n    public void doCompare( Object o1, Object o2 ) {\n      if ( comparator.compare(o1,o2) ) \n        ....\n    }\n\n    @Reference\n    protected setComparator( Comparator c ) {\n       comparator = c;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在您的清单中,只需添加:

\n\n
Service-Component: *\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将由 bnd 接收。因此您的域代码中没有 OSGi 代码。您可能会感到困惑,没有 unset 方法,但 bnd 的默认值是静态绑定。因此,在激活之前会调用 set 方法,而在调用 unset 之前会先停用 set 方法。只要您的 Consumer 对象也是 \xc2\xb5service,您就是安全的。有关 \xc2\xb5services 的更多信息,请参阅bndtoolsbnd主页和我的博客。

\n\n

附言。您的示例是无效代码,因为如果 o1 != o2,o1 将回答大于和小于 o2,这是比较器合约不允许的,并且会使排序不稳定。

\n