OSGI入门:注册一个服务

欢迎回来EclipseZone OSGi迷你系列。终于,我们准备接触Services了。我认为,Service层是OSGi最精彩的部分,所以接下来的部分将会很有趣。

上一次我们看了MovieFinder接口的例子,我们讲了将使用MovieLister搜索影片。事实上你可以认为这个例子——它从Martin Fowler的著名页上的“依赖注入”,也正如所知道的“反转控制”(Inversion of Control)或IoC。

重新用IoC来尝试解决这个问题。一个MovieLister并不特别关心原始电影数据的出处,所以我们使用MovieFinder接口来从它隐藏细节。思想是我们可以代替MovieFinder的任一细节,比如获取数据库或者甚至调用一个Amazon Web Service,既MoiveLister仅仅依赖于这个接口,不是任意具体实现。

到目前为止一切顺利,但是在一些点上,我们必须确实给一个具体的MovieFinder到MovieLister的实现。与其让MovieLister到外面去调用一个查找方法,不如我们用一个外部的容器“推”一个合适的对象给它。因此这个成为反转控制。不少这样的容器已经被开发出来了,例如PicoContainer,HiveMind,Spring甚至是EJB3.0。可是所有这些容器都有一个限制:它们大多是静态的。一旦一个MovieFinder给予了一个MovieLister,它就相当于JVM的生命期。

OSGi也允许我们实现IoC模式,但是在动态方法中。它可能动态的提供MovieFinder的实现给MovieLister并在之后移除它们。接下来,我们能够做到在一个文本文件查找电影的应用程序到使用Amazon Web Services的查找它们的热交换。

这就是服务层帮我们做的。十分简单,我们注册一个MovieFinder服务到Service Regisgry中。之后MovieLister可以用那个MovieFinder服务被提供出来。一个服务因此不比一个Java对象——POJO多些什么——并且它被注册在Java接口的名称下面(一个POJI?)。

这次,我们将这是看看使用registry来注册服务。稍后,我们看看如何获得这个registry外的服务并提供一个MovieLister。

我们将添加上次我们建立的BasicMovieFinder的Bundle。我们不需要修改已存在的类,我们仅仅需要添加一个Bundle的激活器。所以复制以下代码到osgitut/movies/impl/BasicMovieFinderActivator.java文件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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的内容:

1
2
3
4
5
6
7
8
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)"



自从上一次以来,有两个信息被添加到这个manifest。第一个是Bundle-Activator行,它告诉框架关于我们的Bundle的新激活器——我们上次没有用到它。同样,我添加了org.osgi.framework到这个导入到包。正如我们的Bundle的上版本不能同框架交互,它不需要导入这个OSGi API包。

现在你可以重新建立BasicMovieFinder.jar文件:

1
2
> javac -classpath equinox.jar:MoviesInterface.jar osgitut/movies/impl/*.java
> jar cfm BasicMovieFinder.jar BasicMovieFinder.mf osgitut/movies/impl/*.class



回到OSGi控制台,你将看到上次的BasicMovieFinder.jar仍然被安装着。那么你只需要通过输入update N来告诉OSGi去更新这个Bundle,这个N是Bundle的数字标识(你用ss命令找到的那个)。现在使用start N来启动Bundle并且你会看见……很小的事情发生了。

事实上,我们仅仅用OSGi Service Registry注册了我们第一个服务,但是可惜的是没有人在“另一端”,所以这个注册不能产生任何可视化的影响。如果我们想要亲自保证我们的代码实际做了些什么,我们将继续挖掘,并且我们可以使用以下命令:

1
services (objectClass=*MovieFinder)



我们将看到以下输出:

1
2
3
{osgitut.movies.MovieFinder}={category=misc, service.id=22}
  Registered by bundle: file:BasicMovieFinder.jar [4]
  No bundles using service.



很好,我们的服务被注册了,并且我很想继续告诉你如何查找服务并在其他的Bundle中使用它,但是那将在另外一天了。在这期间,看看你可以用services命令做些什么。开始时常是输入没有任何表达式的services,之后——那确实可以通过服务的过滤仅仅显示器中的一个。不使用过滤,你将看到所有的注册了的服务。有着令人惊讶的巨大数字。

你可能感兴趣的:(spring,应用服务器,数据挖掘,IOC,osgi)