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!!");
}
}