1.简介
Open Service Gateway Initiative(OSGi服务平台ServicePlatform)
一个Java框架,可扩展部署和下载的应用程序(bundle)。模块化,可插拔,可动态改变行为,
Java平台的独立性和动态代码加载能力
定义了如何签名和验证一个Bundle
OSGI的核心层次,定义了Bundle模型,Bundle如何Import和Export代码,以及如何定义和解析Bundle之间的依赖关系
定义了如何将一个Java对象注册发布在某个/某些接口下面成为由这些接口表示的服务,获取服务,以及监听某些服务的启动和停止事件等
一个服务可以是一个网络中的设备,如果一个设备被监测到,则服务可以动态注册;如果设备被移除,则服务能够动态注销。在这样的影响环境汇总编程将耗费大量开销来处理动态性,但是OSCi帮助开发者处理了绝大多数动态性方面的工作。
用户登录验证模块:要求可动态的替换(系统运行期)用户登录验证的方式。
例如目前有三种验证方式:LDAP验证,DB验证以及配置文件验证;同事要求可随时增加新的验证方式,如CA验证方式等。
Equinox,成功案例是Eclipse IDE,还有Oscar(不活跃),Knopflerfish
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 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 {
}
}
类似的命令还有install,uninstall等
OSGi中所有模块的部署都必须以Bundle方式来进行部署,Bundle以jar包形式存在的一个模块化物理单元,里面包含了代码、资源文件和元数据(metadata),并且jar包的物理边界也同时是运行时逻辑模块的封装边界。
这个jar和普通jar唯一不同点就是MANIFEST.MF,关于Bundle的所有信息都在其里面进行了描述(如Bundle名称、需要导入的包,输出的包等),官方称为bundle的元数据。
Bundle通过实现BundleActivator接口去控制其生命周期
API由以下三个核心接口组成
1) BundleActivator:捕捉到bundle的start和stop事件
2) BundleContext:一个bundle在框架中的执行时上下文,当启动或停止一个bundle的时候,框架将它发送到一个bundle的激活器
3) Bundle:包含bundle基本信息和bundle生命周期的控制接口
Bundle是个独立概念,在OSGi框架中对于每个Bundle采用的是独立的classloader机制,这也就意味着不能采用传统的引用其他Bundle工程来实现Bundle间的协作,
每个Bundle可以定义输出的包以及引用的包,这样在Bundle间就可以共享包中的类,但在OSGi、框架中更推荐采用Service方式。
Bundle通过BundleContext注册对外提供的服务,同事也可以通过BundleContext来获得需要引用的服务。
两个bundle互相引用对方的包会报错(循环引用),项目会出现红色感叹号
并不特殊,只是可以直接被其他Bundle通过Require-Bundle来使用的Bundle
本身不拥有独立的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!!");
}
}