`
catchid2003
  • 浏览: 18958 次
  • 性别: Icon_minigender_1
  • 来自: 广西
社区版块
存档分类
最新评论

OSGI入门:消费一个服务

    博客分类:
  • OSGI
阅读更多

http://230996.blog.chinajavaworld.com/entry/3690/0/

 

在我们的上个部分,我们看了如何注册一个服务。现在哦我们需要从另外的Bundle查找并使用服务。

我们将问题放到我们的需求的上下文中,那个通过Martin Fowler的依赖反转的页面获得的灵感。我们建立了一个MovieFinder的服务并通过Service Registry注册了它。现在我们想要建立使用了MovieFinder的一个MovieLister来搜索定向的电影。我们假定MovieLister它自己将是被其它Bundle消费的一个服务,例如一个GUI应用程序。问题是,OSGi服务是动态的……它们来去都是动态的。意思就是有时我们想要调用MovieFinder服务但是它恰巧无效。

所以,如果MovieFinder没有呈现,那么MovieLister将做什么?显然,通过MovieLister完成工作的重要部分是调用MovieFinder,所以这有一些有用的选择给我们:
[list=decimal]

  • 生成一个错误,例如返回null或者抛出一个异常
  • 等待
  • 在第一次里不要调用
    [/list]

    在这篇文章中我们将首先看前两项,它们十分简单。第三个选项可能甚至仍然没有什么感觉,但是看过前两个后你将会对它抱有希望。

    第一件事我们需要为MovieLister服务定义接口。复制以下代码到osgitut/movies/MovieLister.java文件中:
    1
    2
    3
    4
    5
    6
    7
    
    package osgitut.movies;
     
    import java.util.List;
     
    public interface MovieLister {
        List listByDirector(String name);
    }
    



    现在创建文件osgitut/movies/impl/MovieListerImpl.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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    
    package osgitut.movies.impl;
     
    import java.util.*;
    import osgitut.movies.*;
    import org.osgi.framework.*;
    import org.osgi.util.tracker.ServiceTracker;
     
    public class MovieListerImpl implements MovieLister {
        private final ServiceTracker finderTrack;
     
        public MovieListerImpl(ServiceTracker finderTrack) {
            this.finderTrack = finderTrack;
        }
     
        public List listByDirector(String name) {
            MovieFinder finder = (MovieFinder) finderTrack.getService();
            if(finder == null) {
                return null;
            } else {
                return doSearch(name, finder);
            }
        }
     
        private List doSearch(String name, MovieFinder finder) {
            Movie[] movies = finder.findAll();
            List result = new LinkedList();
            for (int i = 0; i < movies.length; i++) {
                if(movies[i].getDirector().indexOf(name) > -1) {
                    result.add(movies[i]);
                }
            }
     
            return result;
        }
    }
    



    这可能是我们的目前最长的代码样本!那么这里将要做什么?首先你注意搜索电影的实际的逻辑被分隔在doSearch(String, MovieFinder)方法中,来帮助我们隔离OSGi具体代码。偶然的,我们执行搜索的方式是相当的愚笨和低效率,但是这不是这节指导的重点。我们无论如何只有两个电影在数据库中!

    有趣的部分是在listByDirector(String name)方法中,使用了一个ServiceTracker对象来从Service Registry中获得MovieFinder。ServiceTracker是将最低级别的OSGi API中的大量令人不愉快的细节抽象出来的非常有用的类。然而我们仍然要检查服务是否确实存在。我们采取在我们的构造函数中传递给我们的ServiceTracker。

    注意,你可能见过其他地方的代码从Registry获得一个服务而不使用ServiceTracker。例如,它可能调用BundleContext使用getServiceReference和getService。可是这个代码你不得不写的十分复杂并且它不得不小心的自行清理。以我所见,放到低级别的API中处理的益处很少,并且有很多的问题。总是单独使用ServiceTracker更好。

    一个不错的创建ServiceTracker的地方是在Bundler的激活器中。复制这段代码到osgitut/movies/impl/MovieListerActivator.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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    
    package osgitut.movies.impl;
     
    import java.util.*;
    import org.osgi.framework.*;
    import org.osgi.util.tracker.ServiceTracker;
    import osgitut.movies.*;
     
    public class MovieListerActivator implements BundleActivator {
     
        private ServiceTracker finderTracker;
        private ServiceRegistration listerReg;
     
        public void start(BundleContext context) throws Exception {
            // Create and open the MovieFinder ServiceTracker
            finderTracker = new ServiceTracker(context, MovieFinder.class.getName(), null);
            finderTracker.open();
     
            // Create the MovieLister and register as a service
            MovieLister lister = new MovieListerImpl(finderTracker);
            listerReg = context.registerService(MovieLister.class.getName(), lister, null);
     
            // Execute the sample search
            doSampleSearch(lister);
        }
     
        public void stop(BundleContext context) throws Exception {
            // Unregister the MovieLister service
            listerReg.unregister();
            
            // Close the MovieFinder ServiceTracker
            finderTracker.close();
        }
     
        private void doSampleSearch(MovieLister lister) {
            List movies = lister.listByDirector("Miyazaki");
            if(movies == null) {
                System.err.println("Could not retrieve movie list");
            } else {
                for (Iterator it = movies.iterator(); it.hasNext();) {
                    Movie movie = (Movie) it.next();
                    System.out.println("Title: " + movie.getTitle());
                }
            }
        }
    }
    



    现在来看看这个激活器的启动。首先,在start方法中它创建了一个ServiceTracker对象,在我们刚写的MovieLister中使用。然后“打开”ServiceTracker告诉它启动跟踪Registry中MovieFinder服务的实例。之后,创建我们的MovieListerImpl对象并在Registry注册它到名为“MovieLister”的接口下。最后,为了在我们启动Bundle时看到有意思的事情,激活器靠MovieLister运行了一个简单的搜索并打印出结果。

    我们需要建立并安装这个Bundle。我这次将不给出完整的介绍——你可以复习一下上个部分并使它工作。记得你需要创建一个manifest文件,并且它指示osgitut.movies.impl.MovieListerActivator类为Bundle-Activator。并且Import-Package行需要包含三个包,名称是org.osgi.framework,org.osgi.util.tracker和osgitut.movies。

    一旦你已经安装了MovieLister.jar到Equinox运行时,你可以启动它。在那点上你将看到两条信息中的一条,依赖于是否这个BasicMovieFinder的Bundle在上一次一直在运行。如果它没有运行,你将看到:
    1
    2
    
    osgi> start 2
    Could not retrieve movie list
    


    但是如果它正在运行你将看到:
    1
    2
    
    osgi> start 2
    Title: Spirited Away
    


    通过停止和启动各个Bundle,你将能够显示任一信息。并且那些几乎是这部分的全部,除了记得我说过当一个服务无效时等待的事情?代码我们已经有了,这实际上是很琐碎的:简单的改变MovieListerImpl的16行来调用waitForService(5000)在ServiceTracker上代替getService(),并且添加try/catch块来捕捉InterruptedException。

    listByDirector()方法等待5000毫秒的原因是要等MovieFinder服务被显示出来。如果一个MovieFinder服务那时已经安装了,当然,如果它已经存在——我们将立即获得它来使用。

    通常,我们建议不要像这样挂起线程。特别在这种情况下,它可能很危险因为listByDirector()方法实际是从我们的Bundle激活器的start方法调用的,这是一个从框架线程调用的方法。
    激活器意味着要迅速地返回,因为当一个Bundle启动了的时候会有一定数量的其它事情。事实上最坏的情况下我们可能引起死锁,因为我们会进入一个在属于框架对象的synchronized块,那可能已经被其他的一些给锁定了。通常的做法是从不在Bundle激活器的start方法中处理任何长时间运行或者阻塞操作,或者在框架直接调用的代码不做任何操作。

    在下个部分中,我们将看看在使用应付神奇的第三个选项:“Don’t exist in the first place”。稍候!
  •  

     

    分享到:
    评论

    相关推荐

      OSGi入门篇:服务层

      OSGi(Open Service Gateway Initiative)是一个Java社区定义的模块化服务平台,它允许在同一个运行环境中部署多个版本的同一个组件,而不会相互冲突,从而提供了一个动态的、模块化的运行时环境。OSGi规范定义了...

      OSGI入门和整合Spring

      学习OSGI入门和整合Spring,对于开发复杂的企业级应用,或者想要提升系统灵活性和可维护性的开发者来说,是非常有价值的。通过理解OSGI的模块化机制和Spring的依赖注入原理,可以构建出更加高效和可扩展的Java应用。

      Spring OSGi 入门.pdf

      创建一个服务接口,实现该接口的提供者捆绑,并在消费者捆绑中通过 OSGi 服务注册表查找并使用该服务。 ### 7. 进阶话题 深入学习 Spring OSGi,可以研究安全性、远程服务、事件处理、事务管理等高级特性。同时,...

      精彩:OSGI入门以及提升

      实例代码部分通常会包含实际的OSGI应用示例,比如如何创建一个简单的服务提供者和消费者,或者展示如何在OSGI环境中实现AOP(面向切面编程)。通过这些例子,你可以更直观地理解OSGI的工作原理,并学会在项目中应用...

      osgi入门与实践

      OSGi,全称为 Open Service Gateway Initiative,从字面上理解,它最初被设计为一个面向服务的平台。1999 年,OSGi 联盟成立,旨在为通过网络向设备提供服务建立开放的标准。该联盟的目标是构建一个在广域网和局域网...

      Spring OSGI 快速入门中文教程

      OSGi(Open Service Gateway Initiative)是一种Java模块化系统,它允许开发者创建可热更新、可隔离且互相依赖管理的模块。Spring OSGi是Spring框架与OSGi服务的结合,使得在OSGi环境中使用Spring变得简单。本教程将...

      OSGI 经典实例,入门

      OSGI框架由一组称为"bundle"的模块组成,每个bundle都是一个自包含的Java程序单元,包含类、资源以及元数据。这些bundle可以通过导出和导入包来声明它们提供的服务和依赖的服务。这种模块化设计使得开发者能够轻松地...

      经典OSGI学习资料

      在这个压缩包中,我们可以找到一个名为"OSGI介绍"的文件,它可能包含了OSGI的基本概念、核心特性以及如何开始学习OSGI的相关知识。 首先,OSGI的核心概念是模块系统。在OSGI框架中,每个模块被称为服务单元或bundle...

      OSGi (Open Service Gateway Initiative)入门

      - **服务(Services)**:服务是bundle之间通信的接口,一个bundle可以提供服务(Export),其他bundle则可以消费这些服务(Import)。服务通过Service Registry进行注册和查找,使得服务发现和使用变得简单。 **...

      osgi webservice入门

      OSGi为Java应用提供了一个动态、模块化的运行时环境,使得软件组件可以独立地加载、卸载和更新,而不影响整个系统的运行。 在OSGi环境中实现Web服务,可以极大地提高灵活性和可维护性。Web服务是一种通过网络(通常...

      osgi helloworld

      在OSGi环境中,一个服务可以被其他bundle消费。在`server` bundle中,可能会定义一个公开接口,供其他bundle通过服务注册和查找机制进行交互。这涉及到OSGi框架的核心组件,如BundleContext和ServiceRegistry,它们...

      spring-osgi-1.2.0.zip

      Spring框架是一个强大的轻量级Java应用程序框架,而OSGi则是一种模块化系统,用于管理和部署Java应用程序。在Spring OSGi中,Spring的应用组件可以作为OSGi服务来发布和消费,从而实现更灵活、可插拔的架构。 标题...

      OSGI相关资料

      3. **osgi入门图解.pptx** - 这份PPT可能包含了一套逐步的OSGI入门教程,通过图表和示例帮助初学者理解OSGI的基本概念,比如bundle的结构、配置、依赖关系以及如何构建和运行一个简单的OSGI应用。这种视觉化的学习...

      OSGI Server

      OSGI服务器的核心是Equinox,这是Eclipse项目的一个组成部分,常用于桌面应用和RCP(Rich Client Platform)应用。随着技术的发展,Equinox逐渐被引入到移动设备和手持设备上,而"OSGI Server"项目则旨在消除在...

      osgi gemini blueprint环境

      Gemini Blueprint是OSGi联盟企业专家组(EE Expert Group)开发的一个服务,它提供了对Spring应用上下文在OSGi环境中的支持,使得开发者可以使用Spring的声明式编程模型来编写OSGi服务。 在描述中提到的博文链接,...

      osgi实战(详细文档)

      其中Equinox是Eclipse基金会开发的一个OSGI框架的实现,而Oscar和Knopflerfish也是OSGI社区较为知名的实现。这些框架为OSGI在不同应用场景中的部署和运行提供了基础。 文档中还介绍了OSGI的R4规范,这是OSGI技术的...

      OSGi Technology 教程

      首先,"Getting Started with OSGi 1 Your First Bundle.pdf"是入门篇,讲解了如何创建你的第一个OSGi捆绑包(Bundle)。捆绑包是OSGi的基本模块单位,包含了可执行的Java代码和其他资源。开发者需要了解如何定义...

    Global site tag (gtag.js) - Google Analytics