OkHttp项目中applyOsgi与applyOsgiMultiplatform函数的详细分析
1. 函数实现分析
1.1 applyOsgi函数
graph LR
A[applyOsgi] --> B[创建osgi SourceSet]
A --> C[配置osgiApi依赖]
A --> D[配置Jar任务的BundleTaskExtension]
D --> E[设置类路径]
D --> F[应用bnd属性]
A --> G[在Jar任务完成后添加OSGi元数据]
-
设计目的:为标准JVM项目提供OSGi支持
-
关键特性:
-
创建专用的osgi SourceSet
-
自动添加Kotlin OSGi依赖
-
灵活的bnd配置参数传递
1.2 applyOsgiMultiplatform函数
graph LR
A[applyOsgiMultiplatform] --> B[创建main源集转发到jvmMain]
A --> C[配置osgiApi依赖]
A --> D[配置jvmJar任务的BundleTaskExtension]
D --> E[设置类路径]
D --> F[应用bnd属性]
A --> G[在jvmJar任务完成后添加OSGi元数据]
-
设计目的:解决Kotlin多平台项目与bnd工具的兼容性问题
-
关键特性:
-
创建转发源集解决bnd工具对"main"源集的硬编码依赖
-
特殊处理多平台项目的类路径
-
更复杂的依赖管理
2. 函数应用差异
2.1 标准模块 vs 多平台模块
特性 | applyOsgi (标准模块) | applyOsgiMultiplatform (多平台模块) |
---|---|---|
源集处理 | 创建新的osgi SourceSet | 创建转发到jvmMain的main源集 |
任务配置 | 直接配置Jar任务 | 配置jvmJar任务 |
依赖管理 | 相对简单 | 需要处理多平台依赖 |
兼容性处理 | 无特殊处理 | 解决bnd工具与多平台的兼容性问题 |
2.2 实际应用示例
okhttp-tls模块 (applyOsgi) :
// 简单直接的应用方式
applyOsgi(
"Export-Package: okhttp3.tls,okhttp3.tls.internal.*;okhttpinternal=true;mandatory:=okhttpinternal",
"Import-Package: org.bouncycastle.*;resolution:=optional,*",
"Automatic-Module-Name: okhttp3.tls",
"Bundle-SymbolicName: com.squareup.okhttp3.tls"
)
okhttp主模块 (applyOsgiMultiplatform) :
// 更复杂的配置,处理多平台特性
applyOsgiMultiplatform(
"Export-Package: okhttp3,okhttp3.internal.*;okhttpinternal=true;mandatory:=okhttpinternal",
"Import-Package: " +
"com.oracle.svm.core.annotate;resolution:=optional," +
"org.conscrypt;resolution:=optional," +
"org.bouncycastle.*;resolution:=optional," +
"org.openjsse.*;resolution:=optional,*",
"Automatic-Module-Name: okhttp3",
"Bundle-SymbolicName: com.squareup.okhttp3"
)
3. 设计考量与技术实现
3.1 共同设计原则
1. 模块化配置:
-
将OSGi配置集中管理,避免重复代码
-
提供一致的配置风格
2. 灵活的参数传递:
-
使用可变参数接受bnd配置
-
允许模块自定义OSGi特性
3. 自动化处理:
-
自动添加必要的依赖
-
在构建任务完成后自动生成OSGi元数据
3.2 特殊技术处理
applyOsgiMultiplatform中的转发源集:
val mainSourceSet = object : SourceSet by jvmMainSourceSet {
override fun getName() = "main"
// 重写任务名称避免冲突
override fun getProcessResourcesTaskName() = "${jvmMainSourceSet.processResourcesTaskName}ForFakeMain"
// ...
}
这种设计解决了bnd工具对"main"源集的硬编码依赖问题,是多平台项目能够使用OSGi的关键。
4. 实际效果与最佳实践
4.1 生成的OSGi特性
两个函数最终都会生成包含以下特性的MANIFEST.MF文件:
-
正确的Bundle标识信息
-
精确的包导出控制
-
灵活的包导入策略
-
Java模块系统兼容性
4.2 使用建议
1. 标准JVM项目:
-
使用
applyOsgi
-
保持bnd配置简洁
2. 多平台项目:
-
必须使用
applyOsgiMultiplatform
-
注意处理平台特定依赖
3. 配置原则:
-
明确导出公共API包
-
合理使用optional和resolution指令
-
保持与Java模块系统的一致性