在Java中,是没有模块的概念的。我们不能把一些代码组成一个模块,然后控制那些是可以外部使用的,那些是内部使用的。我们能用的主要有两个办法,一个是把一些内部使用的
类赋予包内访问权限,但是这样在内部使用上会很方便,因为使用这个类的类和这个类本身要在同一个包下;另外一个办法是通过文档告知它是内部类,不能再外部使用,但是这种
限制很容易被忽略。而内部类被外部使用的后果是,不能轻易调整接口,因为不知道内部类是否被外部使用了。如果调整,可能会导致外部系统受很大影响。难道就没有一种机制来
保证我们只暴露想暴露的部分给外部么?、
答案是肯定的,那就是OSGi,OSGi的主要职责就是为了让开发者能够构建动态化、模块化的Java系统。使用OSGi后,应用就可以像搭积木一样完成搭建,例如对于一个正在运行
的系统,其中一个模块使用到了日志服务,但目前系统中没有提供日志服务模块,就可以直接从网上下载实现了日志服务API的模块,然后动态地将此模块进行安装,其他要使用
日志服务的模块就可以使用了。
Bundle
Bundle从形式上讲,是在META-INF目录下的MANIFEST.MF文件中加入了OSGi特定描述的一个jar包。Bundle其实就是OSGi中的模块。Bundle的生命周期被OSGi框架所管理,具
有如下的状态:INSTALLED、RESOLVED、UNINSTALLED、STARTING、ACTIVE、STOPPING.
Bundle通过配置jar包中的MANIFEST.MF,可以控制从Bundle导出的包,而没有导出的包,则在Bundle外部是不够使用的。这样就很好的完成了内部类和外部类的隔离。Bundle
可以被动态安装、启动、停止和卸载。而Bundle也是服务(Service)和组件(Component)的载体。不管是通过BundleContext注册和获取服务方式,还是通过Declarative Service进行注入
的方式,都是在编写Bundle。基于OSGi的应用,就是由一个一个Bundle组成的。Bundle就是我们手中烦人积木,通过OSGi的框架把这些积木组织在一起,就形成了系统。
在OSGi中,每个bundle都有自己独立于其他Bundle的ClassLoader,正因为这样,各个Bundle内部的类是隔离的。一个Bundle可能会用到另外Bundle的类,Bundle之间是要交
互的,一种方式
通过Package的Export和Import来进行,也就是说,提供类的Bundle对外暴露(Export)自己的一个或多个Package,而使用方则根据自己的需要导入(Import)一个或多个Package.
另外一种方式为,通过Service的方式进行。一个Bundle作为Service提供方,对外提供Service,使用者可以查找到提供的Service,并使用这个Service.而提供/使用Service又存在两种方式:
一种是经典的做法,通过BundleContext(Bundle的上下文)来提供和获取;一种是使用Declarative Service来实现。