Bundle的解析过程就是对Bundle的MF文件进行分析,根据配置的依赖关系构造依赖模型。
(源码见:ResolverImpl.resolveBundles0)
假设有2个Bundle,import/export分别是:
BundleA:import pkg.b; export pkg.a; BundleB:import pkg.a; export pkg.b;也就是2个Bundle相互依赖
解析步骤(主要部分):
1、假设首先对BundleA解析,先获取BundleA的所有imports,然后迭代每个import找到匹配的export,并设置import和export的依赖引用关系。
// 设置了依赖引用关系后就知道import是由哪个Bundle导出
export.getExporter().addRef(imp.getBundle());
imp.addPossibleSupplier(export); // 找到pkg.b的一个可能的提供者为BundleB导出的pkg.b
但是,如果自己也export了相同的包,则会被舍弃,会采用它依赖的export。因此,如果一个Bundle import了一个同名的包(自己Bundle也有,而且不管有没有export),则永远不会找到自己包下的类(根据类查找规则,会在依赖的export下寻找)。也就是说,Bundle中包命名一定要注意不要同名。
2、如果export所在的bundle不是已解析(resolved)的,这里的BundleB还没有解析,则开始解析BundleB,同步骤1。
当在解析BundleB的import pkg.a时,发现BundleA还不是已解析(resolved)的(正在解析中resolving),又对BundleA进行解析,同步骤1。
但是,当解析到import pkg.b时,发现它已经有提供者了(前面已经找到了匹配的export),就把该BundleA添加到依赖循环列表中。
这里,BundleA解析结束(没有其他未解析的import了)返回,但状态还是resolving。接着,发现import pkg.a的提供者BundleA为resolving,又把该BundleB添加到依赖循环列表中。
这里,BundleB解析结束(没有其他未解析的import了)返回,但状态还是resolving。
3、循环依赖处理
对解析BundleA涉及的依赖环列表进行依赖检查,如果里面所有Bundle都能正确的找到依赖,则设置它们的状态为已解析(resolved)。
该过程涉及到的相关实体:
Version:表示Bundle或者Package的版本对象。对应的还有个VersionRange,表示版本范围。
VersionSupplier:版本提供者基类,表示一个特定版本的Bundle或者Package(系统可以同时存在多个版本的Bundle或者Package)。
VersionHashMap:用于保存VersionSupplier,它的键为Bundle或者Package的名称,值为与之对应的多个版本构成的数组,定义如下(在父类MappedList中):
// the mapping with key -> Object[] mapping
protected HashMap internal = new HashMap();
该对象用来保存系统所有解析的的exports、bundles和generics(在ResolverImpl中实现)。
对于多个版本的情况,是如何处理的呢?实现了Comparator接口,在compare中处理排序逻辑,源码如下:
// Compares two VersionSuppliers for descending ordered sorts.
// The VersionSuppliers are sorted by the following priorities
// First the resolution status of the supplying bundle.
// Second is the supplier version.
// Third is the bundle id of the supplying bundle.
public int compare(Object o1, Object o2) {
if (!(o1 instanceof VersionSupplier) || !(o2 instanceof VersionSupplier))
throw new IllegalArgumentException();
VersionSupplier vs1 = (VersionSupplier) o1;
VersionSupplier vs2 = (VersionSupplier) o2;
// if the selection policy is set then use that
if (resolver.getSelectionPolicy() != null)
return resolver.getSelectionPolicy().compare(vs1.getBaseDescription(), vs2.getBaseDescription());
String systemBundle = resolver.getSystemBundle();
// 系统Bundle优先
if (systemBundle.equals(vs1.getBundle().getSymbolicName()) && !systemBundle.equals(vs2.getBundle().getSymbolicName()))
return -1;
else if (!systemBundle.equals(vs1.getBundle().getSymbolicName()) && systemBundle.equals(vs2.getBundle().getSymbolicName()))
return 1;
// 已解析的优先于未解析的
if (vs1.getBundle().isResolved() != vs2.getBundle().isResolved())
return vs1.getBundle().isResolved() ? -1 : 1;
// 版本高的优先
int versionCompare = -(vs1.getVersion().compareTo(vs2.getVersion()));
if (versionCompare != 0)
return versionCompare;
// Bundle Id小的优先(优先安装的优先)
return vs1.getBundle().getBundleId() <= vs2.getBundle().getBundleId() ? -1 : 1;
}
BaseDescription:对一个状态的基本描述,所有的描述对象都有一个名称和版本。
VersionConstraint:表示2个Bundle(就require bundle而言)或一个Bundle和一个Package之间的关系(就import/export而言)。
方法isSatisfiedBy(BaseDescription supplier)用来判断约束是否满足。
ResolverConstraint:VersionConstraint辅助类。
GroupingChecker:检查导出包“uses”指令的一致性。 这是一个比较耗时的操作。
分享到:
相关推荐
在Eclipse-OSGi的内核源码分析中,会涉及到对Bundle接口的实现,该接口定义了Bundle的基本行为和属性。 Bundle接口提供了对Bundle状态的管理,具体包括Bundle的操作方法,如启动、停止、更新和卸载,以及获取Bundle...
Eclipse OSGi框架内核源码分析还需考虑如何处理Bundle之间的依赖关系,例如动态加载类和资源,以及处理依赖项的解析。当一个Bundle需要其他Bundle提供的服务时,它必须声明这些依赖项,并在运行时由OSGi框架解析这些...
标题"基于osgi框架实战源码"揭示了本次学习的主题,即OSGi框架在实际项目中的应用。"osgi实战源码"这一描述进一步强调了这是一份可以动手实践的源代码,它以一个具体的购物车案例为背景,展示了如何在项目中运用OSGi...
当bundle启动时,OSGI框架会解析其MANIFEST.MF文件中的元数据,识别出依赖的其他bundle,并确保这些依赖项已启动并可用。 在OSGI中,bundle的依赖关系主要通过MANIFEST.MF文件来定义。这个文件包含了bundle的基本...
通过实际操作和源码分析,读者可以掌握如何构建、部署和管理OSGI模块化的应用。 OSGI实战部分可能会涵盖以下关键知识点: 1. **OSGI基本概念**:介绍OSGI的基本架构,包括Bundle、Service、生命周期管理(启动、...
**文件名称列表解析:** "blueprint-osgi-bundle-master" 可能是项目源代码的主分支,通常包括项目的所有源码、资源文件、构建脚本等,用于克隆或下载到本地进行开发和学习。 **详细知识点:** 1. **OSGi框架**:...
四、源码分析 org.eclipse.osgi-3.7.0.v20110613-sources.jar文件包含了org.eclipse.osgi的源代码,对于开发者来说,这是理解和学习OSGi框架内部运作的重要资源。通过阅读源码,我们可以看到如何创建和管理bundle,...
5. **源码**:提供的源码可能包括了Tomcat的扩展或插件,用于实现OSGi服务的生命周期管理,如启动、停止、更新bundle。 6. **文档**:文档通常会包含集成步骤、配置指南、常见问题解答等,帮助开发者理解和实施...
3. **分析依赖解析**:通过查看类加载器和MANIFEST.MF解析逻辑,理解OSGi如何处理模块间的依赖。 4. **学习模块化设计**:通过源码,我们可以学习如何将一个大型项目拆分为多个模块,并合理定义它们之间的交互。 ...
当bundle之间存在依赖关系时,如果没有正确声明或解析,就可能导致错误。 描述中提到的链接指向了一个博客文章,虽然内容未给出,但通常这样的资源会包含具体错误案例、分析过程和解决方法。在实际问题排查中,日志...
《OSGi实战》源码分析 OSGi(Open Services Gateway Initiative)是一种Java模块化系统,它为构建可扩展、模块化的应用程序提供了强大的框架。OSGi的核心特性是动态性,允许在运行时安装、卸载、启动和停止服务,极...
标题 "很久之前的osgi整理" 暗示了这篇内容可能涉及的是OSGi(OSGi Alliance)技术的早期分析或教程,这是一个用于Java应用程序模块化的框架。在Java开发中,OSGi允许开发者将大型应用分解为独立的、可重用的模块,...
9. **源码分析** 学习OSGi时,深入理解源码可以帮助开发者更好地掌握其实现原理。例如,可以研究Apache Felix或Equinox的源码,了解它们如何处理bundle的加载、依赖解析和服务注册等核心功能。 10. **挑战与解决...
这包括bundle的加载、解析、启动和停止等操作,以及如何通过Equinox API与OSGi服务进行交互。 3. **Bundle开发**:学习如何编写符合OSGi规范的Java代码,创建bundle的manifest.mf文件,声明导出和导入的包,配置元...
至于压缩包内的"整合代码原版",这可能是一个完整的项目源码,包括了OSGi和Spring的配置文件、服务定义、bundle实现、启动脚本等。开发者可以通过分析这些代码,了解如何在OSGi环境下配置和管理Spring应用,以及如何...
在《OSGI进阶.pdf》这本书中,可能涵盖了更深入的话题,比如bundle的打包和部署、服务注册与查找、bundle间通信的协议(如白板模式和Declarative Services)以及如何使用OSGi进行企业级应用开发。这本书可能会详细...
《深入解析Gradle Android插件:ext.bundle.osgi.common-1.0.8.zip与开源项目的融合》 在当今的移动应用开发领域,Android Studio作为主要的集成开发环境,Gradle作为其默认的构建工具,已经成为了开发者不可或缺的...