最近使用OSGi来解决一个集成测试的问题. 感觉还是走了不少弯路, 主要是OSGi的一些习惯思维跟以前的开发思想有一定的区别(主要集中在ClassLoader), 另外一点就是当出现一些莫名其妙的问题, 一般很难知道原因, 需要从出错信息的蛛丝马迹中根据经验进行推理(汗,程序员看推理小说对解决问题很有帮助啊).
本人使用的eclipse版本是3.5.x, 只用到了equinox框架, 使用了里面最简单的功能. 什么spring-dm之类的仅限于hellworld.
org.eclipse.equinox.ds_1.1.1.R35x_v20090806 eclipse是自带的, 不用再下载了
还需要加入org.eclipse.equinox.util_1.0.100.v20090520-1800这个bundle
一个完整的servlet container(jetty)的bundle列表:
引用
0 ACTIVE org.eclipse.osgi_3.5.1.R35x_v20090827
1 ACTIVE org.mortbay.jetty.server_6.1.15.v200905151201
2 ACTIVE org.eclipse.osgi.services_3.2.0.v20090520-1800
4 ACTIVE org.eclipse.equinox.http.servlet_1.0.200.v20090520-1800
5 ACTIVE org.eclipse.equinox.http.jetty_2.0.0.v20090520-1800
9 ACTIVE org.apache.commons.logging_1.0.4.v200904062259
10 ACTIVE javax.servlet_2.5.0.v200806031605
11 ACTIVE org.mortbay.jetty.util_6.1.15.v200905182336
12 ACTIVE org.eclipse.equinox.ds_1.1.1.R35x_v20090806
13 ACTIVE org.eclipse.equinox.util_1.0.100.v20090520-1800
3 ACTIVE LocalDictQuery_1.0.0
6 ACTIVE RemoteDictQuery_1.0.0
7 ACTIVE DictQueryWeb_1.0.0
8 ACTIVE DictQuery_1.0.0
spring-dm需要的bundle列表:
引用
0 ACTIVE org.eclipse.osgi_3.5.1.R35x_v20090827
1 ACTIVE org.springframework.osgi.core_1.2.0
2 ACTIVE org.springframework.context_2.5.6.A
3 ACTIVE org.springframework.aop_2.5.6.A
4 ACTIVE org.springframework.beans_2.5.6.A
5 ACTIVE org.springframework.osgi.extender_1.2.0
6 ACTIVE com.springsource.org.aopalliance_1.0.0
7 ACTIVE org.springframework.core_2.5.6.A
8 ACTIVE org.springframework.osgi.io_1.2.0
9 ACTIVE org.apache.commons.logging_1.0.4.v200904062259
osgi bundle的文件路径一般是这样:
引用
bundleresource://15.fwk21010507:1/
将osgi bundle工程使用bundleresource协议的文件URL转换成使用file协议的URL以便读取
url = org.eclipse.core.runtime.FileLocator.toFileURL(url);
这里需要用到org.eclipse.core.runtime 这个bundle
osgi 的bundle工程, 需要将maven依赖jar包copy到target目录, 可以使用下面的命令:
引用
mvn dependency:copy-dependencies -DoutDirectory=/target/dependency
通过在bundle中通过ClassLoader.getSystemResource("")的起始路径在:
引用
D:/eclipse/eclipse-java-galileo/plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar
碰到最多的是类似的错误:
引用
java.lang.LinkageError: loader constraint violation: when resolving interface method "package.class.method(JLpackage/class;)Ljava/lang/Object;" the class loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) of the current class, package/class, and the class loader (instance of org/eclipse/osgi/internal/baseadaptor/DefaultClassLoader) for resolved class, package/class, have different Class objects for the type package/class used in the signature
这个主要是bundle之间的存在相同的类,导致在各自的ClassLoader找不到导致的. 或者有冲突, 比如在bundleA依赖bundleB, 而且二者同时存在classC, classD, 而且存在classD d = classC.method(), 那么在引用的时候如果存在这样的使用方式: bundleA的classD d = bundleB的classC.method() 那么就会存在上面的问题, 解决办法就是相同的class只存在一份, 然后依赖的时候通过import package的方式来加以引用即可.