OSGi起步(5):使用服务

本文介绍如何在OSGi框架中查找和使用已注册的服务。通过创建MovieLister服务,演示了如何利用ServiceTracker来获取MovieFinder服务,并实现了在服务不可用时的不同处理方式。

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

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

原作者:Neil Bartlett

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

OSGi起步(5):使用服务

 

上一部分,我们知道了如何注册一个服务。这一次,我们来看看怎么去查找和使用另一个bundle注册的服务。

 

和以前一样,我们使用Martin Fowler关于“依赖注入”的论文里提到的例子。我们已经创建了一个MovieFinder,并且把它做为服务注册到注册表中。现在,我们来创建一个MovieLister,它将使用MovieFinder来查找某个导演执导的影片。我们假设MovieLister本身也是一个服务,它将被其他bundle使用,比如一个用户界面程序。这就有麻烦了,因为OSGi的服务是动态的,它们存在与否都是可能的。这意味着,有时候我们想去调用MovieFinder服务,却意外地发现它并不可用!

 

MovieFinder服务不存在的时候,MovieLister该怎么处理呢?很显然,调用MovieFinderMovieLister很重要的一个工作,所以我们只有很少的几个可选的选项:

1、返回一个错误,比如,返回null或者抛出一个异常;

2、等待;

3、一开始就不出现。

本文中,我们将把注意力集中在前两个选项上,因为它们比较简单。一开始,你可能会觉得第三个选项没有任何意义。不过,在我们实现前两种方法以后,它会变得很让人期待。

 

我们要做的第一件事是,为MovieLister定义一个接口。复制以下代码到osgitut/movies/MovieLister.java:

 

package osgitut.movies;

import java.util.List;

public interface MovieLister {

    List listByDirector(String name);

}
 

接着,创建文件 osgitut/movies/impl/MovieListerImpl.java:

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;

    }


}


这大概是到目前为止我们所写的最长的代码了。那么这些代码在做什么呢?首先,我们注意到,为了与OSGi相关的代码保持松散结构,查找电影的实际过程被提取到了doSearch(String ,MovieFinder)方法中。虽然,我们所用的查找方法很差而且没有效率,不过,做为一个教程,这倒是不重要。而且,数据库中只有两部电影:)

 
listByDirector(String name)
方法很有意思,它使用ServerTracker对象从服务注册表中获取MovieFinderServiceTracker是一个很有用的类,它掩盖了OSGi API底层许多乏味的细节。但是,我们仍然需要检查一个服务是否确实存在。我们假设ServiceTracker将在构造函数中传入。

bundler的控制器(activator)中创建ServiceTracker是一个不错的主意。复制以下代码到osgitut/movies/impl/MovieListerActivator.java

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());

            }


        }


    }


}
 

现在,这个activator开始变得有趣起来了。首先,在start方法中,创建了一个ServiceTracker(服务追踪器)对象,它将被我们刚刚写的MovieLister使用。接着,这个“追踪器”被“释放”,并开始在注册表中查找MovieFinder服务。然后它创建MovieListerImpl对象,并把它以“MovieLister”注册到服务注册表中。最后,为了在启动bundle的时候发生一些有趣的事情,activator简单地搜索了一下MovieLister然后输出结果。

我们需要编译并安装这个bundle。这一次,我不再给出完整的指令。你应该能够根据之前所做的实现这个操作。记住,你还需要创建一个manifest文件,并指明它的Bundle-Activatorosgitut.movies.impl.MovieListerActivator。另外,Import-package一行应该包含三个从其它bundle导入的package,分别是:org.osgi.framework, org.osgi.uitl.trackerosgitut.movies.

一旦你把MovieLister.jar安装到Equinox的运行环境中,你就可以启动它了。这时,你将看到两条或者三条消息,这取决于BasicMovieFinder bundle自从上一次起是否还在继续运行。如果没有,你将看到:

osgi> start 2

Could not retrieve movie list

如果在运行,将看到

osgi> start 2

Title: Spirited Away
 

停止或者启动不同的bundle,你将看到你希望的每一条消息。这差不多就是本次要讲的所有内容了,除了我刚才说的,当一个服务不可用的时候,你还可以选择等待。由现有的代码,应该是很容易实现的:把MovieListerImpl的第16行的getService()改为调用ServiceTrackerwaitForService(5000),然后添加try/catch块来处理异常InterruptedException

 
一般来说,我不建议像这样子将一个线程挂起。这种情况是很危险的,因为listByDirector()方法是由bundleactivatorstart方法调用的,而它将被框架线程调用。activator通常被要求快速返回,因为当一个bundle处于活动状态的时候,将有一系列的事情发生。事实上,在最坏的情况下,还可能产生死锁,因为我们进入了到框架所拥有的一个对象的synchronized(同步)段中,而这个对象很可能已经被别的东西给阻塞了。一个比较好的建议是,永远不要再一个bundleactivatorstart方法中,或者直接被框架调用的代码中,进行长时间的操作和阻塞。

 
下一次,我们将看看当依赖不存在的时候,如何实现第三种方法:“一开始就不出现”。不要走开。

 

这是一个基于AI视觉识别与3D引擎技术打造的沉浸式交互圣诞装置。 简单来说,它是一棵通过网页浏览器运行的数字智慧圣诞树,你可以用真实的肢体动作来操控它的形态,并将自己的回忆照片融入其中。 1. 核心技术组成 这个作品是由三个尖端技术模块组成的: Three.js 3D引擎:负责渲染整棵圣诞树、动态落雪、五彩挂灯和树顶星。它创建了一个具备光影和深度感的虚拟3D空间。 MediaPipe AI手势识别:调用电脑摄像头,实时识别手部的21个关键点。它能读懂你的手势,如握拳、张开或捏合。 GSAP动画系统:负责处理粒子散开与聚合时的平滑过渡,让成百上千个物体在运动时保持顺滑。 2. 它的主要作用与功能 交互式情感表达: 回忆挂载:你可以上传本地照片,这些照片会像装饰品一样挂在树上,或者像星云一样环绕在树周围。 魔法操控:握拳时粒子迅速聚拢,构成一棵挺拔的圣诞树;张开手掌时,树会瞬间炸裂成星光和雪花,照片随之起舞;捏合手指时视线会拉近,让你特写观察某一张选中的照片。 节日氛围装饰: 在白色背景下,这棵树呈现出一种现代艺术感。600片雪花在3D空间里缓缓飘落,提供视觉深度。树上的彩色粒子和白色星灯会周期性地呼吸闪烁,模拟真实灯串的效果。 3. 如何使用 启动:运行代码后,允许浏览器开启摄像头。 装扮:点击上传照片按钮,选择温馨合照。 互动:对着摄像头挥动手掌可以旋转圣诞树;五指张开让照片和树化作满天星辰;攥紧拳头让它们重新变回挺拔的树。 4. 适用场景 个人纪念:作为一个独特的数字相册,在节日陪伴自己。 浪漫惊喜:录制一段操作手势让照片绽放的视频发给朋友。 技术展示:作为WebGL与AI结合的案例,展示前端开发的潜力。
【顶级EI复现】计及连锁故障传播路径的电力系统 N-k 多阶段双层优化及故障场景筛选模型(Matlab代码实现)内容概要:本文提出了一种计及连锁故障传播路径的电力系统N-k多阶段双层优化及故障场景筛选模型,并提供了基于Matlab的代码实现。该模型旨在应对复杂电力系统中可能发生的N-k故障(即多个元件相继失效),通过构建双层优化框架,上层优化系统运行策略,下层模拟故障传播过程,从而实现对关键故障场景的有效识别与筛选。研究结合多阶段动态特性,充分考虑故障的时序演化与连锁反应机制,提升了电力系统安全性评估的准确性与实用性。此外,模型具备良好的通用性与可扩展性,适用于大规模电网的风险评估与预防控制。; 适合人群:电力系统、能源互联网及相关领域的高校研究生、科研人员以及从事电网安全分析、风险评估的工程技术人员。; 使用场景及目标:①用于电力系统连锁故障建模与风险评估;②支撑N-k故障场景的自动化筛选与关键脆弱环节识别;③为电网规划、调度运行及应急预案制定提供理论依据和技术工具;④服务于高水平学术论文复现与科研项目开发。; 阅读建议:建议读者结合Matlab代码深入理解模型构建细节,重点关注双层优化结构的设计逻辑、故障传播路径的建模方法以及场景削减技术的应用,建议在实际电网数据上进行测试与验证,以提升对模型性能与适用边界的认知。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值