`
C_J
  • 浏览: 127967 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

体验OSGi(helloworld.jar)—富app的热拔插

阅读更多

    记得以前工作的时候,有天direct manager问我在tomcat下的应用A要使用应用B下的某个类,我告诉他是不行的,因为JDK对于类加载有命名空间,不同的命名空间之间相互不影响,即使类名相同,这也为了JVM的安全着想,所以tomcat为应用A和应用B都创建了各自类加载的命名空间从而相互不影响。

    而OSGi的设计理念看上就是把各种功能及服务做成Bundle并热拔插。换句话说,应用A,B此时被当作组件存活在OSGi平台上,B中的某个类可以公开出去,让其他组件可见,或者B中的某个类实例注册到OSGi容器中(类似解耦的方式之一),这样应用A就可以类似组件一样使用应用B中的资源了。

    这种模块化和热拔插的设计理念最流行的应用应该算eclipse吧,eclipse plugin就是这样加载模块化的方式,我觉得还是不错的,给我最爽的感觉就是一个应用的功能基本上都是由不同的人不同时间以组件方式被挂载到eclipse平台上面。

 

    其实,在自己的开发工作当中也是分模块实现应用不同的功能,并因为需求是变化的,说不定哪天XX需求就不要了,要新增YY需求,为了不修改过多的代码,保持开闭原则,所以在coding的时候也是非常注意模块化设计,并达到模块的可配置性。但那只是代码级别上的模块化,代码级别的好处是模块和模块之间的相互调用非常方便,适用于有一定耦合度的情况,而OSGi貌似实现了一个JVM层面的模块化,模块与模块之间如果要耦合的话,需要以上提到的export或注册。

    如果app应用比较单一,感觉就没必要了,有点大题小做。当然,如果建立这样的平台很轻松的话,又未尝不是一种新的尝试。

 

    那如何基于OSGi平台开发应用app呢?

在网上找到一篇简单的应用:http://blog.csdn.net/zouzhile/archive/2010/01/03/5124243.aspx

建立的Bundle是建立在felix框架上,所需要的软件:

 

==================================================================================

Eclipse:3.3.1

Felix binary:http://labs.xiaonei.com/apache-mirror/felix/felix-framework-2.0.1.zip

Felix 源代码:http://download.csdn.net/source/1958471

BND 编辑器:http://www.aqute.biz/repo/biz/aQute/bnd/0.0.384/bnd-0.0.384.jar

注释:1)BND编辑器是一个很轻的工具,能够帮助我们从.bnd文件自动在Eclipse中生成Bundle的jar文件

==================================================================================

 

详细的步骤请参见原作者的博客。

 

 

自己只写了一个简单的helloworld测试了下,如下:

 

package org.osgi.helloworld;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;


public class HelloWorld implements BundleActivator{

	static {	
		System.out.println("in static");
	}
	public static ExecutorService excutor=Executors.newFixedThreadPool(1);
	public void start(BundleContext arg0) throws Exception {
		System.out.println("start");
		excutor.execute(new oneThread());
		
	}

	public void stop(BundleContext arg0) throws Exception {
		System.out.println("stop");
		excutor.shutdown();
	}

	class oneThread implements Runnable{

		public void run() {
			System.out.println("Working....");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
}

 

 

写完app后,就需要利用bnd工具打包成一个jar,并符合OGSI的Bundle规范,然后加载到felix这个容器里,详细步骤请见上面博客。

然后启动felix的shell脚本,如下: 

 

java -jar felix.jar [felix-cache-path]
Welcome to Felix
================


-> ps
START LEVEL 1
   ID   State         Level  Name
[   0] [Active     ] [    0] System Bundle (2.0.1)
[   1] [Active     ] [    1] Apache Felix Bundle Repository (1.4.2)
[   2] [Active     ] [    1] Apache Felix Shell Service (1.4.1)
[   3] [Active     ] [    1] Apache Felix Shell TUI (1.4.1)
-> install file:src/helloworld.jar // app打成的jar包
Bundle ID: 6
-> start 6 // 运行helloworld
in static
start
-> Working....

-> stop 6 // 停止helloworld
stop
-> 

 

 

 

从结果看,还是挺吸引人的,实现了模块的热拔插,程序由原来的main()入口变为了start(),模块退出时,则调用stop()方法。

但整个过程Console只输出一次“Working”字样。

 

 

打成的jar包结构也很简单:

 

meta-inf

              /manifest.mf

org/

             osgi/

                    helloworld/ *.class

 

 

其中mf为osgi的元数据描述文件,如下:

 

Manifest-Version: 1.0
Private-Package: org.osgi.helloworld
Bundle-Version: 0
Tool: Bnd-0.0.384
Bnd-LastModified: 1287414214125
Bundle-Name: helloworld
Bundle-ManifestVersion: 2
Created-By: 1.6.0-beta2 (Sun Microsystems Inc.)
Bundle-Activator: org.osgi.helloworld.HelloWorld
Import-Package: org.osgi.framework;version="1.5"
Bundle-SymbolicName: helloworld

 

到此我体验到了在一个JVM里模块以jar形式实现的热拔插,OSGi还有个特色是这些Bundle之间如何实现类共享呢?

 

关于felix的使用,截取官方的一点文字:

写道

Starting the Framework
Start the framework from the installation directory by typing:

java -jar bin/felix.jar
The framework launcher starts the framework and installs and starts all bundles contained in the bundle directory of the current directory. By default, the bundle directory contains shell-related bundles providing a textual user interface to interact with the framework. Bundles installed into the framework are copied into a bundle cache directory for subsequent executions. By default, the framework creates a cache directory, called felix-cache, in your current working directory. If you want to start the framework using a different bundle cache directory, you can do so like this:

java -jar bin/felix.jar <cache-path>
Where <cache-path> is the path you want to use as the bundle cache. If you specify a relative cache path, then it will be treated as relative to the current working directory.


Installing Bundles
A bundle is the OSGi term for a component for the OSGi framework. A bundle is simply a JAR file containing a manifest and some combination of Java classes, embedded JAR files, native code, and resources. A bundle may provide some specific functionality for the user or it may implement a service that other bundles can use; bundles can only use functionality from other bundles through shared services and packages.

The Felix framework distribution comes with three bundles, which are located in the bundle/ directory of the framework distribution installation directory. These bundles include the Gogo Runtime (core command processing functionality), Gogo Shell (text-based shell user interface), Gogo Command (basic set of commands), and Bundle Repository (a bundle repository service). In addition to these bundles, the bundle repository provides access to other bundles for easy installation. The bundle repository service provides a set of shell commands in the obr:* scope; refer to the Apache Felix OSGi Bundle Repository for more information.

Before installing any bundles, it is important to understand how bundles are manually deployed into the framework. Bundles are deployed in two stages; first they are installed, then they are started. To install a bundle use the felix:install shell command followed by a bundle URL. For example, to install a bundle.jar bundle you type:

felix:install file:/path/to/bundle/bundle.jar
Once a bundle is installed, it can then be started by using the felix:start command and the bundle identifier of the desired bundle. The felix:lb command is used to list installed bundles and to obtain the bundle's identifier. The following Felix shell session illustrates how to start the bundle.jar bundle:

g! install file:/path/to/bundle/bundle.jar

 

 

ps:附件是eclipse的实例代码

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics