偶也开始研究OSGi了,这东西真不错。不过官方的OSGi标准包太大了,前两天偶根据规范实现了其Module Layer部分并根据大家提到的一些不足,增加了自定义ClassPath和NativeCode的功能,这下应该可以用在基于Spring的 Webapp上了~
不多说了,看看测试代码吧:
- public class TFramework extends TestCase {
- private Framework framework;
- public void setUp() {
- framework = new Framework();
- framework.addFrameworkListener( new IFrameworkListener() {
- public void frameworkEvent(IFrameworkEvent event) {
- if (event.getMessage() != null ) {
- System.out.println(event.getMessage());
- }
- if (event.getThrowable() != null ) {
- event.getThrowable().printStackTrace();
- }
- }
- });
- }
- public void tearDown() {
- framework = null ;
- System.out.println();
- }
- public void testBundle() throws Exception {
- framework.addClassPath( "C:\\osgi\\ws\\commons-logging.jar" );
- framework.addLibraryPath( "C:\\osgi\\os" );
- // ----------------------------------------------
- // Bundle-SymbolicName: com.yipsilon.osgi.test
- // Bundle-Version: 1.0.0.20061212
- // Bundle-NativeCode: swt-gdip-win32-3235.dll,swt-awt-win32-3235.dll,swt-wgl-win32-3235.dll,swt-win32-3235.dll
- // Bundle-Activator: com.yipsilon.osgi.test.Activator
- // Export-Package: com.yipsilon.osgi.test
- // Import-Package: org.apache.commons.logging
- // Bundle-ClassPath: swt.3.2.1.v3235.jar
- // ----------------------------------------------
- framework.installBundle( "C:\\osgi\\test.jar" );
- ClassLoader cl = framework.getClassLoader();
- URL explicitURL = cl.getResource( "com/yipsilon/osgi/test/Test.class" );
- URL implicitURL = cl.getResource( "com/yipsilon/osgi/test1/Hello.class" );
- URL externalURL = cl.getResource( "org/apache/commons/logging/LogFactory.class" );
- System.out.println( "implicitURL: " + (implicitURL != null )); // Returns true
- System.out.println( "explicitURL: " + (explicitURL != null )); // Returns true
- System.out.println( "externalURL: " + (externalURL != null )); // Returns true
- Class explicitClass = cl.loadClass( "com.yipsilon.osgi.test.Test" );
- Class implicitClass = cl.loadClass( "com.yipsilon.osgi.test1.Hello" );
- Class externalClass = cl.loadClass( "org.apache.commons.logging.LogFactory" );
- System.out.println( "implicitClass: " + (implicitClass != null )); // Returns false
- System.out.println( "explicitClass: " + (explicitClass != null )); // Returns true
- System.out.println( "externalClass: " + (externalClass != null )); // Returns true
- }
- }
看完了知道这东西该怎么用了吧... 嘿嘿!!
不过要真正实现Webapp功能,还需要加一些东西,这些稍后我会开发出来~~进度的快慢全凭偶的空闲时间的多少... faint
PS:怎么附件加不进去呐??才1.5MB而已....
继“偶也研究OSGi了之一 ”之后不到12小时,偶又开始发博了,大家检查一下内容质量如何~
这次,在上次的示例基础上,展示一下MINI OSGi的一些基本特性。还是刚才的代码(有少许变化):
PS:为了简化代码,省略了所有的注释,代码结构还算不错,一般可以看懂~
- public class TFramework extends TestCase {
- private Framework framework;
- public void setUp() {
- framework = new Framework();
- framework.addFrameworkListener( new IFrameworkListener() {
- public void frameworkEvent(IFrameworkEvent event) {
- if (event.getType() != IFrameworkEvent.TYPE.DEBUG && event.getMessage() != null ) {
- System.out.println(event.getMessage());
- }
- if (event.getThrowable() != null ) {
- event.getThrowable().printStackTrace();
- }
- }
- });
- framework.addBundleListener( new ISynchronousBundleListener(){
- public void bundleChanged(IBundleEvent event) {
- IBundle bundle = event.getBundle();
- System.out.println( "Bundle(SymbolicName:" + bundle.getSymbolicName() + ") state is changed to " + event.getType().name());
- }
- });
- }
- public void tearDown() {
- framework = null ;
- }
- public void testBundle() throws Exception {
- framework.addClassPath( "C:\\osgi\\lib" );
- framework.addClassPath( "C:\\osgi\\lib\\commons-logging.jar" );
- IBundle[] bundle = framework.installBundles( "C:\\osgi" );
- bundle[ 0 ].start();
- }
- }
看到了吧,这里使用Bundle对象了~看看Bundle所对应的Activator类吧:
- public class Activator implements IBundleActivator{
- public void start(IBundleContext context) throws Exception {
- System.out.println( "Test.start(" + context + ")" );
- }
- public void stop(IBundleContext context) throws Exception {
- System.out.println( "Test.stop(" + context + ")" );
- }
- }
"C:\osgi"目录下有一个叫 test.jar 的bundle包,MANIFEST.MF文件内容为:
Bundle-SymbolicName: com.yipsilon.osgi.test
Bundle-Version: 1.0.0.20061212
Bundle-NativeCode: swt-gdip-win32-3235.dll,swt-awt-win32-3235.dll,swt-wgl-win32-3235.dll,swt-win32-3235.dll
Bundle-Activator: com.yipsilon.osgi.test.Activator
Export-Package: com.yipsilon.osgi.test
Import-Package: org.apache.commons.logging
Bundle-ClassPath: swt.3.2.1.v3235.jar
其中 test.jar 的文件结构为:
test.jar
│ swt-awt-win32-3235.dll
│ swt-gdip-win32-3235.dll
│ swt-wgl-win32-3235.dll
│ swt-win32-3235.dll
│ swt.3.2.1.v3235.jar
│
├─com
│ └─yipsilon
│ └─osgi
│ ├─test
│ │ Activator.java
│ │ Test.java
│ │
│ └─test1
│ ApplicationWindow.java
│ Hello.java
│
└─META-INF
MANIFEST.MF
使用JUnit3运行TFramework后,后台打印出:
01. Bundle(SymbolicName:com.yipsilon.osgi.test) state is changed to INSTALLED
02. Bundle(SymbolicName:com.yipsilon.osgi.test) state is changed to RESOLVED
03. Bundle(SymbolicName:com.yipsilon.osgi.test) state is changed to STARTING
04. Test.start(com.yipsilon.osgi.BundleContext@14a9972)
05. Bundle(SymbolicName:com.yipsilon.osgi.test) state is changed to STARTED
06. Bundle(SymbolicName:com.yipsilon.osgi.test) state is changed to STOPPING
07. Test.stop(com.yipsilon.osgi.BundleContext@14a9972)
08. Bundle(SymbolicName:com.yipsilon.osgi.test) state is changed to STOPPED
09. Bundle(SymbolicName:com.yipsilon.osgi.test) state is changed to UNINSTALLED
目前,MINI OSGI已经实现了import-package和require-bundle的resolve检查(也就是输出第2行的执行结果)。
我使用了addShutdownHook来在系统退出时释放所有没有卸载的bundle资源,以防止内存泄漏(第6-9行就是自动释放的输出)。
目前Module Layer部分还没有完全实现MANIFEST属性条件的判断,我觉得那个东西太复杂,大多数情况也用不上(至少以我现在的项目来说),所以先搁置一下。其他重要的功能就剩下update()方法了。HOHO~~