当前位置:   article > 正文

OSGi框架

osgi框架

1.简介

1.1 what

Open Service Gateway Initiative(OSGi服务平台ServicePlatform)

一个Java框架,可扩展部署和下载的应用程序(bundle)。模块化,可插拔,可动态改变行为,

1.2 advance

Java平台的独立性和动态代码加载能力

1.3 parts
1.3.1 安全层

定义了如何签名和验证一个Bundle

1.3.2 模块层

OSGI的核心层次,定义了Bundle模型,Bundle如何Import和Export代码,以及如何定义和解析Bundle之间的依赖关系

1.3.3 生命周期层
定义了Bundle的生命周期包括的状态以及状态之间如何转换,并且定义了接口支持Bundle的生命周期操作,包括Install, start, stop, update和uninstall。OSGi提供了Bundle库(BundleRepository)
1.3.4 服务层

定义了如何将一个Java对象注册发布在某个/某些接口下面成为由这些接口表示的服务,获取服务,以及监听某些服务的启动和停止事件等

1.4 application
1.4.1 应用一

一个服务可以是一个网络中的设备,如果一个设备被监测到,则服务可以动态注册;如果设备被移除,则服务能够动态注销。在这样的影响环境汇总编程将耗费大量开销来处理动态性,但是OSCi帮助开发者处理了绝大多数动态性方面的工作。

1.4.2 应用二

用户登录验证模块:要求可动态的替换(系统运行期)用户登录验证的方式。

例如目前有三种验证方式:LDAP验证,DB验证以及配置文件验证;同事要求可随时增加新的验证方式,如CA验证方式等。

1.5 知名OSGi框架

Equinox,成功案例是Eclipse IDE,还有Oscar(不活跃),Knopflerfish


2.Hello World

2.1 New工程
 
附:这是稍微复杂一点的应用
        

Zzhello:

public interface Hello {
	public void syaHello();
}
public class HelloImpl implements Hello{
	final String helloString;
	
	public HelloImpl(String helloString) {
		this.helloString = helloString;
	}
	
	@Override
	public void syaHello() {
		System.out.println(this.helloString);
	}
	
}
Export-Package: zzhello;version="1.0"
public class Activator implements BundleActivator {
	
	private List<ServiceRegistration> registrations = 
			new ArrayList<>();

	public void start(BundleContext context) throws Exception {
		registrations.add(context.registerService(Hello.class.getName(), 
				new HelloImpl("Hello, OSGi"), null));
		System.out.println("OSGi-服务注册成功");
	}
	
	public void stop(BundleContext context) throws Exception {
		for(ServiceRegistration registration: registrations){
			registration.unregister();
			System.out.println("取消服务注册:"+registration);
		}
	}

}

ZzhelloClient:

Bundle-Activator: zzhelloclient.HelloUser
Import-Package: org.osgi.framework;version="1.3.0",
 zzhello;version="1.0.0"
public class HelloUser implements BundleActivator{
	@Override
	public void start(BundleContext ctx) throws Exception {
		ServiceReference reference = ctx.getServiceReference(Hello.class.getName());
		if (reference != null) {
			Hello hello = null;
			try {
				hello = (Hello)ctx.getService(reference);
				if(hello != null)
					hello.syaHello();
				else
					System.out.println("Services:Hello---object null");
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				ctx.ungetService(reference);
				hello = null;
			}
		}else {
			System.out.println("Service:Hello---not exists");
		}
	}

	@Override
	public void stop(BundleContext arg0) throws Exception {
		
	}
	
}
2.2 Debug环境Configuration设置(全选的话会报错)

2.3 结果


类似的命令还有install,uninstall等

3.Bundle

OSGi中所有模块的部署都必须以Bundle方式来进行部署,Bundle以jar包形式存在的一个模块化物理单元,里面包含了代码、资源文件和元数据(metadata),并且jar包的物理边界也同时是运行时逻辑模块的封装边界。

这个jar和普通jar唯一不同点就是MANIFEST.MF,关于Bundle的所有信息都在其里面进行了描述(如Bundle名称、需要导入的包,输出的包等),官方称为bundle的元数据。

3.1 类加载机制
在使用一个bundle之前,必须对共享的包之间的约束关系进行解析。解析过程就是确定导入包如何连接到导出包。解析过程必须在bundle中任何代码加载或运行之前。
在多数Java应用中,通常是由一个Class Loader来加载所有的类和资源文件,而在OSGi模块层中(一个模块就是一个Bundle)则为每个模块提供了各自的Class Loader,从而保证了模块的闭合,同时为模块的关联提供控制

3.2 生命周期

Bundle通过实现BundleActivator接口去控制其生命周期

3.2.1 Bundle六种状态
1)installed:Bundle已经成功安装
2)resolved:Bundle所需要的类都已经可用了,该状态表明Bundle已经准备好了用于启动或者说Bundle已经被停止
3)starting:Bundle正扎起启动中,BundleActivator的start方法已经被调用不过还没返回
4)active:Bundle已启动,并在运行中
5)stopping:Bundle正在停止中,BundleActivator的stop方法已经被调用,不过还没返回
6)uninstalled:Bundle已经被卸载了

API由以下三个核心接口组成
1) BundleActivator:捕捉到bundle的start和stop事件
2) BundleContext:一个bundle在框架中的执行时上下文,当启动或停止一个bundle的时候,框架将它发送到一个bundle的激活器
3) Bundle:包含bundle基本信息和bundle生命周期的控制接口

3.3 Bundle引用

Bundle是个独立概念,在OSGi框架中对于每个Bundle采用的是独立的classloader机制,这也就意味着不能采用传统的引用其他Bundle工程来实现Bundle间的协作,

3.1.1 定义输出的包以及引用的包

每个Bundle可以定义输出的包以及引用的包,这样在Bundle间就可以共享包中的类,但在OSGi、框架中更推荐采用Service方式。

3.1.2 Service方式

Bundle通过BundleContext注册对外提供的服务,同事也可以通过BundleContext来获得需要引用的服务。

3.1.3 Bundle相互调用

两个bundle互相引用对方的包会报错(循环引用),项目会出现红色感叹号

3.4 三种特殊的Bundle
3.4.1 Require Bundles

并不特殊,只是可以直接被其他Bundle通过Require-Bundle来使用的Bundle

3.4.2 Fragment Bundles

本身不拥有独立的classloader,可以看成是Bundle的一种附属,片段。片段的关键用途是提供不同区域的翻译文件,这样就可以实现翻译文件从主要应用的bundle中独立出来。可以用来夸张host bundle的功能,做一些bundle的依赖类
--> New Fragment Project


启动后会发现片段不能够自己启动

主Bundle代码:

public class Activator implements BundleActivator {
        // 去读配置文件,默认就是读主啊,为什么网上会说从会覆盖掉主呢???
	public void start(BundleContext context) throws Exception {
		InputStream is = Activator.class.getResourceAsStream("/META-INF/myConfig.properties");
		Properties properties = new Properties();
		properties.load(is);
		System.out.println("name"+properties.getProperty("name"));
	}
	
	public void stop(BundleContext context) throws Exception {
		System.out.println("Goodbye World!!");
	}
}






本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
  

闽ICP备14008679号