在我们上个指导部分,我们看了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的研究中。
分享到:
相关推荐
Jar转换为Bundle工具,需要的可以下载
android bundle和activity之间交换数据
你可以尽可能的让资源再bundle之间重用,而不用担心需要修改代码。 - 增量构建。 跳过没有改动过的bundle来进行构建。像你的编译器一样智能。 - 下载优先级。 自动化的下载优先级管理。下载管理器将根据优先级顺序...
NULL 博文链接:https://salever.iteye.com/blog/1474694
该软件包提供了一种非常简单的方法来添加Symfony Bundle之间的依赖关系。 Composer在非常柔软的层中定义了这些定义,仅下载了这些依赖包。 捆绑软件还应强制其他捆绑软件在应用程序中实例化,以符合依赖关系注入的...
依赖包 解决appium-doctor报bundletool.jar cannot be found问题 解决appium-doctor报bundletool.jar cannot be found问题 解决appium-doctor报bundletool.jar cannot be found问题 解决appium-doctor报bundletool....
它能够自动管理AssetBundle之间复杂的依赖关系,它通过引用计数来维护AssetBundle之间的依赖。你既可以预加载一个AssetBundle,自己管理它的释放,也可以直接通过异步的资源加载函数直接加载资源,资源加载函数会...
Android中用来在Activity之间传递数据可以用Bundle,这是一个在两个Bundle间用Bundle传递数据和接收数据的小例子
Intent_Bundle_传参数
针对所有Angular 2相关包的依赖bundle
TheLastGhost's Bundle
包含Bundle两种传递数据方式,一种是传递简单数据,另一种是传递自定义数据
matlab开发-BundleAdjustment。解束平差(共线方程)摄影测量的一个简单函数
package-bundle允许您以原始tar.gz格式(包括其依赖项)下载npm软件包,并将它们另存为存档在npm文件夹结构中。 然后可以将包导入到包管理器(例如,然后在脱机环境中使用。 入门 使用以下方法下载软件包: npm ...
android activity bundle 通信示例
bundle adjustment tri
linux操作系统的mysql8 rpm-bundle.tar包 mysql-8.0.28-1.el7.x86_64.rpm-bundle.tar
swiper-bundle.min.js
androidbundle
Android 通过Intent使用Bundle传递对象 Android开发中有时需要在应用中或进程间传递对象,下面详细介绍Intent使用Bundle传递对象的方法。 被传递的对象需要先实现序列化,而序列化对象有两种方式:java.io....