OSGi 起步(4): 注册服务

我的懒毛病又开始犯了……一定要克服,坚持!

-------------------------

原始地址:http://www.eclipsezone.com/eclipse/forums/t90688.html

原作者: Neil Bartlett

--------------------------

OSGi 起步(4): 注册服务

欢迎回到Eclipse ZoneOSGi教程。我们终于要开始讲服务了。在我看来,服务层是OSGi中最有意思的一部分,所以接下来的几篇文章将很有意思。

 
上一次,我们看了关于MovieFinder接口的例子,它将被MovieLister用来查找电影。事实上,你可以注意到这个例子来自Martin Fowler著名的论文依赖注入(Dependency Injection)”(http://www.martinfowler.com/articles/injection.html),也被称为”Inversion of Control”或者IoC(控制倒置?)

 

首先回忆一下IoC期望解决的问题。对于MovieLister,一般来说,它并不关心电影记录的原始数据是从哪里来的,所以我们用MovieFinder接口隐藏了这些细节。由于MovieLister只依赖于接口,而不是接口的具体实现,所以我们可以为之提供MovieFinder的不同实现,比如有的是从数据库中获取数据,有的则是通过调用Amazon网络服务接口获取数据。

 

到目前为止,一切都很顺利,但是我们还需要给MovieLister提供一个MovieFinder的具体实现。我们通过外部容器把一个合适的对象“推”给MovieLister,而不是让它自己去调用某个特定的查找方法。这就是所谓的“控制倒置”。现在已经很多种容器被开发出来,比如PicoContainerHiveMindSpring,以及EJB3.0。但是,到目前为止,这些容器都存在着一个缺陷:他们大多是静态的。一旦MovieLister获得MovieFinder,这种联系就会在JVMJAVA虚拟机)的整个生命期中被保持。

 

OSGi同样实现了IoC模式,但是是以动态的方式实现。它使得,动态地为MovieLister提供MovieFinder的实现,并能在需要时动态卸载,成为一种可能。这样,我们可以实现“热交换”,比如把一个从纯文本文件中寻找电影数据的应用替换成从Amazon网络服务查找数据的应用。

 

OSGi的服务层帮我们实现了这种可能。简单来说,首先,我们将一个MovieFinder在服务注册表里注册成一个服务;然后,这个MovieFinder服务被提供给MovieLister。一个服务,其实只是一个Java对象(POJO),当然如果你愿意,也可以说它是以Java接口的名义注册的(POJI)。

 

首先,我们来看看如何注册一个服务。然后,我们将看到怎么从注册表中获得服务并提供给MovieLister

 

我们讲要把上次创建的BasicMovieFinder bundle注册成服务。我们并不需要对现有的类进行修改,只需要添加一个bundle activator(控制器?)。复制以下内容到 osgitut/movies/impl/BasicMovieFinderActivator.java :

package  osgitut.movies.impl;

 

import  org.osgi.framework. * ;

 

import  osgitut.movies. * ;
import  java.util.Properties;
import  java.util.Dictionary;

public   class  BasicMovieFinderActivator  implements  BundleActivator  {

    
private ServiceRegistration registration;

    
public void start(BundleContext context) {

        MovieFinder finder 
= new BasicMovieFinderImpl();

        Dictionary props 
= new Properties();

        props.put(
"category""misc");

        registration 
= context.registerService(

                               MovieFinder.
class.getName(),

                               finder, props);

    }


    
public void stop(BundleContext context) {

        registration.unregister();

    }

}


 

然后将BasicMovieFinder.mf的内容替换为:

Manifest-Version:  1.0

Bundle-ManifestVersion: 
2

Bundle-Name: Basic Movie Finder

Bundle-SymbolicName: BasicMovieFinder

Bundle-Version: 
1.0.0

Bundle-Activator: osgitut.movies.impl.BasicMovieFinderActivator

Import-Package: org.osgi.framework
,

 osgitut.movies
; version="[1.0.0,2.0.0)"

 

跟上一次相比,增加了两样内容。首先是,Bundle-Activator行,它告诉框架bundleactivator是哪个(这个我们上一次没有用到)。另外,还增加了一个导入packageorg.osgi.framework。上一个版本的bundle因为不需要与框架进行交互,所以它不需要导入OSGi API package

 

重新创建BasicMovieFinder.jar

javac -classpath equinox.jar:MoviesInterface.jar osgitut/movies/impl/*.java

jar cfm BasicMovieFinder.jar BasicMovieFinder.mf osgitut/movies/impl/*.class
 

现在回到OSGi的控制台,应该能看到上一次安装的BasicMovieFinder.jar。所以,我们只需要告诉OSGi更新这个bundle,输入命令update N。这个N是这个bundleID(通过输入命令ss可以得到)。启动bundle,你将看到……几乎什么都没有发生。(译者-_-!)

 

事实上,我们只是在OSGi服务注册表例注册了第一个服务。但是,不幸的是,在“另一端”不存在任何对象。所以,并没有任何可见的内容被看见。如果想要确定我们的代码是否真的起效果了,我们需要进一步深入研究,输入以下命令:

 

services (objectClass = *MovieFinder)

我们将看到以下输出:

 

{osgitut.movies.MovieFinder} = {category = misc ,  service.id = 22 }

  Registered by bundle: file:BasicMovieFinder.jar 
[ 4 ]

  No bundles using service.

 

太棒了,这表示我们的服务注册成功了。我很想继续下去,告诉你们怎么去查找服务和在其它的bundle中使用它,不过,这些得等到明天再讲了。你可以看看通过services还能做些什么。对于初学者而言,试试输入不带参数的services吧(它的参数是为了显示我们需要的服务的过滤器),你将看到所有已经注册的服务列表。这个数目是相当庞大。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值