同OSGi的类加载模型相似,多个JIOPi模块运行在同一个JVM之内,但互相并不可见。JIOPi使用与OSGi相似但不完全相同的类加载规则以保证模块间既可以相互隐藏模块的具体实现,又可以通过接口相互使用。
JIOPi v0.1是为兼容纯POJO设计的,可以直接将POJO类库放入JIOPi模块库而无需做任何改动,因此,在JIOPi v0.1的类加载模型中,并没有为模块间的相互依赖提供很好的支持,除非是在特别有意的部署方式下,或使用JIOPi提供的反射机制访问,否则JIOPi模块间的相互访问是比较困难的。
JIOPi的名字(Java Interface Oriented Programming initiative )已经指出,JIOPi模块的服务导出是借助接口来完成的。当然,如果使用JIOPi提供的反射机制进行模块访问,那么就无所谓服务的导出了,模块间也是可以任意互相访问的,在这种模式下,服务的导出是借助JIOPi提供的API来完成的。
所以,为了不使用JIOPi的接口使用反射机制来访问模块,一个模块至少应该由两个Jar包组成:一个为导出的服务接口API的Jar包,该Jar一般情况下应只包含接口类(Interface),而不包含实现类(Class),以后简称为API.jar。另一个是对模块接口API的实现类,以后简称为IMPL.jar。
为了描述JIOPi模块的类加载机制,我们先定义两个名词:
系统层,即由ContextClassLoader及其父ClassLoader加载的类,当前应用的类程序也就是被加载在系统层的,自然JIOPi的API也存在于该层。对于应用而言,该层的类都必须是唯一的,不可能存在同一类的多个版本。
模块层,由JIOPi容器创建的ClassLoader加载的类,不同模块的不同版本的类将被加载在不同的模块层。
由ClassLoader机制不难理解,系统层的类是不能直接访问到模块层的类的,所以对模块的访问需要借助JIOPi的API。
那么模块层的类是否可以访问系统层的呢?
JIOPi对模块层的类加载优先级是这样定义的:
1. 从Bootstrap加载(如java.*的类)
2. JIOPi的API(org.jiopi.framework.*)必须由系统层加载
3. 从当前模块包含的Jar包中加载
4. 从系统层加载
也就是说模块层的类可以访问系统层的类,在要访问的类没有被包含在该模块的Jar包中时,也正因为如此,模块才可以借助部署在系统层的接口,将对当前模块对象的访问暴漏给系统层的类。
然而由于当前模块Jar包优先加载规则,如果模块中已经部署了API.jar,那么对该模块的访问便只能通过JIOPi的API了。而如果不在模块中部署API.jar,而系统层也没有部署,那么该模块在类加载时便会出现接口类无法找到的问题。这就导致如果模块中不包含API.jar,那么就必须在系统层部署,否则模块无法运行;而如果部署了,那就只能通过JIOPi的API来访问了。
这个冲突是可以借助动态代理类来解决的,即永远在模块中部署API.jar,当系统层也部署了API.jar时,使用动态代理类来解决由不同ClassLoader加载的同名类赋值时产生的强制类型转换异常。
考虑到动态代理类存在性能问题,并且在草案中的JIOPi已经制定了解决该冲突的编程风格,所以没有将自动动态代理列入规范之中。
因此,在JIOPi v0.1中(或者说直接将POJO放入JIOPi模块库的模式中),对于一个模块,你只能在 使用接口访问 和 JIOPi模式访问 之中二选一,或者将一个模块发布成两个,一个包含API.jar而另一个则不包含,这也就是为什么HelloWorld演示程序中会出现 jiopi.ibean.helloworld.m 和 jiopi.ibean.helloworld.i 两个模块的原因了。
基于上述的模块类加载原则,你有以下几种方式控制 系统层与模块、模块与模块 的访问方式。
全部使用JIOPi的API
在这种模式下,各个模块程序完全运行在自己的ClassLoader中,无论是系统层访问模块,还是模块之间的互相访问,均借助JIOPi来进行,这种方式的优点是使用最为简单的,并且为使用各种JIOPi模块,项目的lib中只需部署一个JIOPi实现容器的Jar即可,各个模块之间也可直接借助JIOPi的API访问其他模块。但缺陷是无法得到编译器和IDE的支持,写出的代码出错率会比较高,而且代码可读性较差,由于使用反射机制调用,性能也会有所影响。
全部模块只使用IMPL.jar部署
在这种模式下,必须将系统层直接或间接使用到的模块所需的API.jar均部署在系统层,为了避免代码中出现JIOPi的API代码,应当使用其他IoC容器,如Spring来完成系统层对所需各个模块的依赖关系的注入配置。
关于ContextClassLoader的特殊规则
由于ContextClassLoader(Thread.currentThread().getContextClassLoader())的特殊性,特别是一些类库程序在初始化时会从ContextClassLoader中获取类,如大多数xml解析程序,log4j等,如果在模块中部署了这些类库,就会因为模块类加载器的非Java标准的类加载次序规则而出现问题,因此JIOPi规定在类初始化阶段(从类的加载到对象实例的生成过程),JIOPi容器应当将ContextClassLoader设置为当前模块的类加载器,并在加载完毕后设置回原ContextClassLoader,以保证在一些模块的初始化阶段直接从ContextClassLoader中获取类时能够被正确执行。因此如果你的模块直接或间接(如使用xml)的从ContextClassLoader获取对象,那么你应当保证在类或类对象的初始化阶段完成该类语句的执行。
分享到:
相关推荐
C#类库是预定义的一组函数、接口和类,它们封装了常见的编程任务,如文件操作、网络通信、数据库交互等。这些类库通过.NET框架提供,开发者可以方便地调用,极大地提高了开发效率。C#类库包括系统类库(如System.IO...
其中 `System.Xml` 命名空间提供了用于读取、写入、查询和修改 XML 文档的对象模型和方法,例如 `XmlDocument` 类。 2. **System.Windows.Forms**:该 DLL 包含 `System.Windows.Forms` 和 `System.Windows.Forms....
3. **文档/视图架构**:这是MFC的核心特性,用于分离数据(文档)和显示(视图),并由CDocument和CView类来实现。 4. **控件类**:如CButton、CEdit、CListBox等,它们是对Windows控件的封装,使开发者可以方便地...
基于java的开发源码-PList类库 Blister.zip 基于java的开发源码-PList类库 Blister.zip 基于java的开发源码-PList类库 Blister.zip 基于java的开发源码-PList类库 Blister.zip 基于java的开发源码-PList类库 Blister...
基于java的开发源码-EPUB类库 Epublib.zip 基于java的开发源码-EPUB类库 Epublib.zip 基于java的开发源码-EPUB类库 Epublib.zip 基于java的开发源码-EPUB类库 Epublib.zip 基于java的开发源码-EPUB类库 Epublib.zip ...
基于java的开发源码-JSON类库 Flexjson.zip 基于java的开发源码-JSON类库 Flexjson.zip 基于java的开发源码-JSON类库 Flexjson.zip 基于java的开发源码-JSON类库 Flexjson.zip 基于java的开发源码-JSON类库 Flexjson...
语言程序设计资料:Java-类库简介.ppt
解决这些问题的方法包括使用特殊的热部署插件,如JRebel,它通过改变类加载机制来实现实时代码更新,并处理好类的缓存和静态变量问题。另外,开发者还可以通过调整类加载策略,比如使用自定义类加载器,来避免类冲突...
dtree是支持动态树生成的一个js类库,及其方便
Java 类加载器是Java虚拟机(JVM)的核心组成部分,它负责将编译后的字节码文件(.class文件)加载到JVM中并转换为运行时的数据结构。Tomcat,作为广泛使用的Java Servlet容器,它自定义了一套类加载机制,以满足Web...
-PRODAVE6.Dll控件请与接口类库控件放在一起使用; -类库使用没有任何限制; -西门子通讯的前提需要安装西门子编程软件,建立好控制面板的西门子PG/PC通讯通道,并设定好指定符对应的硬件通道,比如 S7ONLINE通道名称对应...
WINDOWS程序员使用指南(二)----MICROSOFT基本类库WINDOWS程序员使用指南(二)----MICROSOFT基本类库
NET4.6-Framework类库 概要说明 81页 NET4.6-Framework类库 概要说明 81页NET4.6-Framework类库 概要说明 81页NET4.6-Framework类库 概要说明 81页
- 窗体在类库中可能需要手动处理生命周期事件,如初始化、加载、关闭等,因为不再有自动的`Main`方法来启动窗体。 - 类库中的窗体可能需要更精细的权限控制,因为它们不再运行在应用程序的上下文中。 9. **优点**...
基于java的开发源码-SQL解析类库 SQLJEP.zip 基于java的开发源码-SQL解析类库 SQLJEP.zip 基于java的开发源码-SQL解析类库 SQLJEP.zip 基于java的开发源码-SQL解析类库 SQLJEP.zip 基于java的开发源码-SQL解析类库 ...
类加载器不仅实现了类的加载功能,还确保了Java程序在多线程环境中的安全性和隔离性。类加载器的设计遵循双亲委派模型,它分为三个主要部分:启动类加载器、扩展类加载器和应用类加载器。 #### 二、类加载过程 类...
类加载器的主要任务是动态加载和管理类,使得程序可以在运行时发现和使用新的类。此外,类加载器具有缓存机制,如果已经加载过一个类的字节码,后续再次请求该类时,不会重复加载,而是直接使用内存中的字节码。 2....
这对于理解MFC的工作原理和在实际项目中有效利用MFC功能至关重要。无论你是要学习MFC的基础知识,还是解决特定问题,这份资料都将是一个宝贵的资源。通过深入学习和实践,你将能够熟练掌握MFC,开发出功能强大且用户...
Java 类加载原理是Java运行时环境中的核心机制之一,它涉及到类的生命周期、类加载器的层次结构以及类的查找和加载过程。了解这一机制对于深入理解Java平台的工作原理至关重要,尤其是在开发自定义类加载器或者处理...