在我们上个指导部分,我们看了Bundle如何能启动和停止,和它们如何能与框架交互和每一个生命周期。那么Bundle真正能做什么呢?
Bundles是一个模块。它们允许我们分割我们完整的项目为能够被单独载入到OSGi运行时的可管理的片段。问题是,是否我们喜欢与否,模块总是以来在一些其他的模块上。在原来旧的Jar里,从没有一个可靠的方法来指定一个对其他Jar的依赖(有的,manifest文件中的Class-Path条目不是做这个的可靠方法)。因此,你从不能真正明确是否这个代码在Jar包里正常工作,或者在运行时将抛出ClassNotFoundException异常。
OSGi非常优美的修正了这个问题。但是展示出来比告诉你更好……那么让我们赶紧获得这些代码。不幸的是我们知道现在还在使用默认的包,但是这不会再继续了;我们将开始使用正式的包来开始工作。所以让我们使用一个非常简单的JavaBean风格的类开始,你要复制以下代码到osgitut/movies/Movie.jar文件中:
1
2
3
4
5
6
7
8
9
10
11
12
|
package osgitut.movies;
public class Movie {
private final String title;
private final String director;
public Movie(String title, String director) {
this.title = title; this.director = director;
}
public String getTitle() { return title; }
public String getDirector() { return director; }
}
|
现在我们将在相同的包里创建一个接口。创建文件osgitut/movies/MovieFinder.java,并复制以下代码到里面:
1
2
3
4
5
|
package osgitut.movies;
public interface MovieFinder {
Movie[] findAll();
}
|
现在让我们将这两个类放到一个Bundle中。是的,我们的Bundle将荒谬的小而且几乎没用,但是现在已经OK了。就像之前我们需要创建一个manifest文件一样,打开MoviesInterface.mf,并且拷贝下面的内容到里面:
1
2
3
4
5
6
|
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Movies Interface
Bundle-SymbolicName: MoviesInterface
Bundle-Version: 1.0.0
Export-Package: osgitut.movies;version="1.0.0"
|
在这里有了一个之前我们没见过的新的行:Export-Package。这只是说包osgitut.movies从这个Bundle被输出了。这可能第一次看的话有些莫名其妙,因为在旧的Jar包里,所有的东西都被输出了。但是你没曾想在你的Jar中能看见的内部中放入一些代码?当然,你能建立一些private或protected的类,但是它们在你的Jar中都不可见。所以OSGi有效的引入了一个新的代码保护级别:如果包在你的Bundle中没有在Export-Package列表中出现,那么它只能在你的模块内部被访问到。
你也可能注意到了我们在包的后面附着了个版本号。这个很重要我们稍后将见到。它不是绝对需要提供一个版本号的,顺便说一句,如果你没做,OSGi将自动的分配版本号“0.0.0”给你的包。我认为总是明确的添加一个版本号是很好的策略。
现在我们来建立这个Bundle:
1
2
|
> javac osgitut/movies/Movie.java osgitut/movies/MovieFinder.java
> jar -cfm MoviesInterface.jar MoviesInterface.mf osgitut/movies/*.class
|
我们先不把这个Bundle安装到运行时。首先,我们将建立依赖于它的另一个Bundle。我们要创建一个具体的MovieFinder接口的实现,那么复制以下代码到osgitut/movies/impl/BasicMovieFinderImpl.java文件中:
1
2
3
4
5
6
7
8
9
10
11
12
|
package osgitut.movies.impl;
import osgitut.movies.*;
public class BasicMovieFinderImpl implements MovieFinder {
private static final Movie[] MOVIES = new Movie[] {
new Movie("The Godfather", "Francis Ford Coppola"),
new Movie("Spirited Away", "Hayao Miyazaki")
};
public Movie[] findAll() { return MOVIES; }
}
|
现在我们需要一个manifest文件,那么创建BasicMovieFinder.mf:
1
2
3
4
5
6
|
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Basic Movie Finder
Bundle-SymbolicName: BasicMovieFinder
Bundle-Version: 1.0.0
Import-Package: osgitut.movies;version="[1.0.0,2.0.0)"
|
注意了我们导入了从另一个包输出的osgitut.movies包。我们也在此时添加了导入版本号的范围。框架在运行期使用范围来匹配导入一个适合的输出。OSGi为版本范围使用了一个语法,与将会与绝大多数的数学方式一样熟悉:方括号意味着包括含(inclusive),圆括号意味着排除(exclusive)。我们将有效的指定版本“1.x”
再说一下,在import上添加一个版本约束在这个例子中不是必需的,这仅仅是采取一个好的习惯。
现在我们来编译和建立我们今天第二个Bundle:
1
2
|
> javac -classpath MoviesInterface.jar osgitut/movies/impl/BasicMovieFinderImpl.java
> jar -cfm BasicMovieFinder.jar BasicMovieFinder.mf osgitut/movies/impl/*.class
|
最终我们准备在这个Equinox里试试这些Bundle。我这次将不给全面的介绍了,我认你应该学会它。首先安装BasicMovieFinder这个Bundle,然后运行ss。你将发现这个Bundle处于INSTALLED状态:
1
2
3
|
id State Bundle
0 ACTIVE org.eclipse.osgi_3.3.0.v20070208
4 INSTALLED BasicMovieFinder_1.0.0
|
你的Bundle列表看起来可能会与我的有些不同,详细点说Bundle ID将取决于你在上次安装和卸载了HelloWorld多少次。以下你需要从思想上转换Bundle ID)。
INSTALLED仅仅意味着框架得到了这个Bundle,但还没有分析它的依赖。一个方法,使用refresh命令强制Equinox来分析我们的Bundle。那么输入refresh 4然后运行ss,你将看到如下:
1
2
3
|
id State Bundle
0 ACTIVE org.eclipse.osgi_3.3.0.v20070208
4 INSTALLED BasicMovieFinder_1.0.0
|
Bundle还是没有被分析!当然,我们需要安装包含Movie类和MovieFinder接口的“接口”Bundle。要确定是这个问题,输入 diag 4来获得诊断信息:
1
2
|
file:BasicMovieFinder.jar [4]
Missing imported package osgitut.movies_[1.0.0,2.0.0).
|
没错,这就是问题所在:我们没有导入osgitut.movies包,因为没有Bundle输出它。那么现在安装MovieInterface.jar的Bundle,并运行ss,列表将看起来如下:
1
2
3
4
|
id State Bundle
0 ACTIVE org.eclipse.osgi_3.3.0.v20070208
4 INSTALLED BasicMovieFinder_1.0.0
5 INSTALLED MoviesInterface_1.0.0
|
最后的步骤是让Equinox再次尝试分析BasicMovieFinder的Bundle,运行refresh 4。ss命令将输出如下:
1
2
3
4
|
id State Bundle
0 ACTIVE org.eclipse.osgi_3.3.0.v20070208
4 RESOLVED BasicMovieFinder_1.0.0
5 RESOLVED MoviesInterface_1.0.0
|
BasicMovieFinder的Bundle现在被RESOLVED了!这是一个必须的步骤,因为直到Bundle处于RESOLVED前它都不能启动,并且它不能提供依赖给其他的Bundle。
注意,通常像这样手工分析不是必需的。通常Bundle将在它们被需要的时候自动被分析——例如,注意MovieInterface的Bundle现在是RESOLVED,尽管我们没有明确的refresh它。
暂且到这里。如果对使用Equinox Console做的事情感兴趣,那么看看IBM开发网络上的Chirs Aniszczyk的精彩文章。为下个部分保持状态,我们将开始进入到OSGi Services的研究中。
分享到:
相关推荐
4. **启动顺序**:如果bundle之间有依赖关系,需要合理设定启动顺序,以保证依赖关系的正确性。 总的来说,"Jar转换为Bundle工具"是OSGI开发中必不可少的一环,它帮助开发者将Java项目转变为可插拔、可管理的模块,...
这篇博客“浅析OSGI的bundle依赖”可能探讨了如何管理和解决这些模块间的依赖问题。 首先,我们来看一下OSGI中的bundle生命周期。一个bundle可以处于未安装、已安装、启动、暂停、停止或卸载这六种状态之一。当...
在Android应用开发中,Bundle和Activity之间的数据交换是至关重要的操作。Bundle对象是Android系统用于存储和传递数据的一种容器,而Activity则是应用程序的基本组件,负责显示用户界面并处理用户交互。理解如何有效...
你可以尽可能的让资源再bundle之间重用,而不用担心需要修改代码。 - 增量构建。 跳过没有改动过的bundle来进行构建。像你的编译器一样智能。 - 下载优先级。 自动化的下载优先级管理。下载管理器将根据优先级顺序...
同时,`Bundle`中的数据在进程崩溃或系统重启后会丢失,因为它依赖于`Intent`的生命周期。如果需要持久化的数据存储,应考虑使用SharedPreferences、SQLite数据库或者文件系统。 在实际项目中,我们常常会遇到...
《jersey-bundle-1.9.1.jar.zip:Java RESTful Web服务的关键组件》 在Java开发领域,jersey-bundle是一个至关...在遇到相关异常时,应首先检查项目配置和依赖管理,确保jersey-bundle的正确引入,以避免运行时错误。
4. **添加依赖**: 在`<dependencies>`标签下,列出所有bundle所依赖的外部库。每个依赖项都需要指定groupId, artifactId和version。 5. **运行Maven构建**: 在Eclipse中,可以通过右键点击项目 -> Run As -> Maven ...
它提供了界面,帮助开发者查看每个AssetBundle的内容,检查资源之间的依赖关系,以及进行打包和加载的测试。 总的来说,AssetsBundle技术是Unity开发中的重要组成部分,它提高了游戏的性能和可维护性,而编辑器扩展...
Bundle 提供了一种灵活的方式来存储和传递数据,使得开发者可以轻松地在不同的 Activity 之间传递数据。 在 Android 中,Bundle 是一个键值对的映射,每个键对应一个特定的值。开发者可以使用 Bundle 来存储字符串...
给这个新的Bundle项目命名,比如"ResourcesBundle",并添加到你的主项目中,使其成为主项目的依赖。 打包Bundle时,我们需要将所有资源文件(如图片、音频等)放入Bundle项目,并确保它们被正确地添加到项目构建...
Bundle则是一个用来存储键值对的数据结构,常用于Activity之间传递数据。本示例将深入探讨如何在Android活动中利用Bundle进行通信。 首先,理解Activity的基本概念至关重要。Activity是Android系统中的窗口,它负责...
在Android开发中,Bundle是一个非常重要的工具类,用于在组件之间传递数据。它通常被用于Activity、Fragment或者Intent之间的数据交换。本篇文章将详细讲解Bundle的两种主要数据传递方式:传递简单数据和传递自定义...
该软件包提供了一种非常简单的方法来添加Symfony Bundle之间的依赖关系。 Composer在非常柔软的层中定义了这些定义,仅下载了这些依赖包。 捆绑软件还应强制其他捆绑软件在应用程序中实例化,以符合依赖关系注入的...
Visual Studio 2015(VS2015)提供了一系列工具来帮助开发者构建这样的安装包,但有时候,为了确保所有依赖项都得到妥善处理,可能需要额外的组件,这就是“VS2015 制作安装包额外需要安装的软件VSI_bundle”的作用...
在Android开发中,Bundle是一个非常重要的工具类,用于在组件之间传递数据。它是一个键值对的集合,通常被用来在Activity、Fragment或者Intent之间共享数据。本文将深入解析`Bundle`类及其在Android基础知识中的应用...
在Android应用开发中,`Bundle`是一个至关重要的类,它被广泛用于在Activity、Fragment以及Intent之间传递数据。`Bundle`本质上是一个可序列化的Key-Value存储容器,它提供了多种方法来存储各种类型的数据,如基本...
3. **依赖加载**:Asset Bundle可能包含其他Asset Bundle的引用,例如一个场景可能依赖多个模型和纹理。Unity提供`AssetBundle.LoadAll`函数,可以一次性加载Asset Bundle及其所有依赖。 4. **热更新加载**:在游戏...
在创建Intent后,我们可以通过`putExtra()`方法为Intent添加键值对,但当数据类型复杂时,可先创建一个Bundle对象,然后用`putExtras(Bundle)`方法将Bundle添加到Intent中。例如: ```java Bundle bundle = new ...
依赖包 解决appium-doctor报bundletool.jar cannot be found问题 解决appium-doctor报bundletool.jar cannot be found问题 解决appium-doctor报bundletool.jar cannot be found问题 解决appium-doctor报bundletool....
3. **Fragment参数传递**:Fragment之间的通信也经常依赖Bundle。在创建Fragment时,可以通过setArguments(Bundle)方法传入数据,然后在Fragment的onCreate()或onCreateView()方法中使用getArguments()来获取。 4. ...