【问题标题】:OSGi loose-coupling best practiceOSGi 松耦合最佳实践
【发布时间】:2011-06-24 04:55:23
【问题描述】:

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

我将使用example from the Felix SCR pages

示例服务是一个比较器

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;
    }
}

上面的代码不包含框架管道,它集中且简洁。在使用 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>

Service-Component: OSGI-INF/sample.xml

一切都很好,我的服务实现与 OSGI 完全没有耦合。

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

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

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

protected void activate(ComponentContext context) {
    Comparator c = ( Comparator ) context.locateService( "sample.component" );
}

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

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

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

两者都不是非常繁重,尽管我认为您最终可能会在类中重复大量此类代码,这使得过滤的噪音更大。

我可以看到的一个可能的解决方案是使用 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);
    }
}

虽然我不确定你会如何在 SCR 配置中进行安排。

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

那么,现在您已经阅读了所有内容,您认为在不使用框架代码“污染”应用程序代码的情况下使用 OSGi 提供的服务的最佳方式是什么?

【问题讨论】:

    标签: java design-patterns osgi


    【解决方案1】:

    1) 我不认为绑定方法会污染您的代码,它们只是 bean setter(您也可以称它们为 setXXX 更传统)。你也需要那些用于单元测试。

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

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

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

    Service-Component: *
    

    这将被 bnd 接收。因此,您的域代码中没有 OSGi 代码。您可能会感到困惑,没有 unset 方法,但 bnd 的默认值是静态绑定。因此 set 方法在您被激活之前被调用,而您在 unset 被调用之前被停用。只要你的 Consumer 对象也是一个 µservice,你就是安全的。查看bndtoolsbnd 主页和我的blogs,了解有关 µservices 的更多信息。

    PS。您的示例是无效代码,因为如果 o1 != o2,o1 将同时回答大于和小于 o2 的问题,这是 Comparator 合约不允许的,并且会使排序不稳定。

    【讨论】:

      【解决方案2】:

      我会告诉你我们在我的项目中是如何做到的。作为一个 OSGi 容器,我们使用 Fuse ESB,尽管可以在 Apache Karaf 内部的某个地方找到。为了不污染我们的代码,我们使用 Spring DM (http://www.springsource.org/osgi),它极大地促进了与 OSGi 容器的交互。它“作为我们持续集成过程的一部分”(最新版本)针对 Equinox 3.2.x、Felix 1.0.3+ 和 Knopflerfish 2.1.x 进行了测试。

      这种方法的优点:

      • xml 文件中的所有“osgi”配置 - 代码未污染
      • 能够使用不同的 OSGi 容器实现

      它看起来怎么样?

      • 在 OSGi 注册表中发布服务:

      • 从 OSGi 注册表导入服务:

      此外,为了创建有效的 OSGi 包,我们使用 maven-bundle-plugin。

      【讨论】:

        【解决方案3】:

        felix 注释与 aQute.bnd.annotations.component 中的相比的优势似乎在于,bind 和 unbind 方法是由 felix scr 插件自动创建的(您可以注释私有字段)。 felix 插件的缺点是它作用于 Java 源代码,因此不适用于用其他语言(例如 scala)创建的类文件。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-12-16
          • 1970-01-01
          • 2017-05-09
          • 2013-12-11
          • 1970-01-01
          • 1970-01-01
          • 2011-12-23
          相关资源
          最近更新 更多