利用动态类加载技术调式ECLIPSE插件
eclipse平台提供runtime方式调试插件和RCP项目,但随着插件项目越写约复杂,启动时间也越来越长,特别是集成了诸如 Hibernate和Spring之类的容器级框架的时候。仅仅为了调试代码中一些琐碎的片段而频繁的重启项目实在是一件异常烦人的工作。
即使重启了项目也许还没完。为了使项目处于某个特定的状态下以方便测试,每次都要重新操作一遍前面业务流程,这同样是十分令人厌倦的。
eclispe使用了OGSI作为微内核,引入了一些动态特性。但是OSGI的动态特性是在保持平台运行的情况下动态更新Bundle,也就是说需要重启插件才能完成动态加载的过程。有没有一些更加细粒度的动态载入方案呢?
在Tomcat下开发过web项目的人都知道,使用调试模式来部署项目即”热部署”可以实现动态载入class文件,让程序员得以动态调试项目。今天向大家提供的这个jar包使得这种效果可以在eclipse runtime上实现。
这是我在自己的插件平台项目——SCOOP框架中使用的几个包。
它可以非常好的解决动态类载入的问题,包括内部类的动态载入都可以很好解决。
其他的几个包还进行了以下尝试
1. 使用元数据标注的办法解决SWT UI 线程的种种问题
2. 还提供了eclipse流程框架的简单实现,以规范插件开发。特别是提出了一个面向业务而不是面向技术的工作流概念,使得编码粒度变大,并得以提高效率。另外这个简单的流程框架还将前面的两种机制很好的结合起来,并且可以和eclipse平台的一些复杂机制解耦,为复杂流程的开发测试提供了方便。为将来实现自定义脚本语言(比如某个类似于BPEL的工作流语言)开发eclise插件项目甚至使用图形化的开发奠定了一定的基础。
我给出了一个完整的示例——JAXB插件。很多框架同jaxb一样提供了code generation工具,可以在这个例子的基础上经过简单修改为这些框架提供插件,比如CXF插件、AXIS2插件等等。
动态类载入编码原则
使用动态类载入机制来进行调试在编码上有一定限制。
首先是要进行动态载入的实例不要在非动态域进行引用。只有这样,当一个流程结束时此实例才会在jvm中得以释放。当然,非要在其他地方进行引用从而长久的在运行时保持这个实例也是有解决方案的(可以使用代理类技术来实现,具体解决办法不在本文之内)。
其次是进行接口同实现类的分离或父类同子类的分离,以隔离不同的class load scope。接口由父类载入器载入,不同的实现(比如修改后的实现)由不同的子类载入器载入。使得最终同一个类型由同一个类载入器载入,这样才能符合jvm的类载入规范。在父类载入域的父类型的方法的参数类型及返回值类型也不能在动态域中。
最后,那些注册在扩展点上的类如ActionDelegate和WorkbenchPart等是不能够动态载入的,他们必须由eclipse提供的类载入器载入(平台会自动载入并管理其生命周期)。如果需要让这些类也动态载入,就需要在平台提供的动态注册机制基础上使用代理或像EJB2.0一样使用侵入式编译来实现代理机制,这个话题同样不在本文之内。
下面就举例说明使用方法
因为时间有限我无法详尽的完成此文,请感兴趣的朋友自己阅读示例源码。
1. 几种动态类载入的办法
(1) 使用手动编码进行类载入
因为会使二次开发人员产生迷惑,故未举例
(2) 在调试时使用spring文件配置动态类载入域
Spring配置文件同样也是动态的,而且会使调试开发工作变得更加清晰,推荐使用
(3) 使用Flow框架来进行动态类载入
2. 使用元数据标注解决UI线程访问的问题
使用三个元数据及动态代理类解决SWT及Eclipse的线程问题。
3. 同eclipse内部机制解耦以方便开发和测试
开发插件项目很多时候需要实现Eclipse内部的一些回调接口来实现功能,这对程序员的水平是一种考验,也使得插件开发工作更加复杂化。比如在实现progressMonitor的时候,就需要实现它的回调接口,将业务逻辑放置在其指定的回调接口——runable接口来实现,这是非常不方便的。我们需要是一种可以提供功能的工具类,像调用一个普通javaBean一样来调用它,而不是将我们的业务代码变形撕碎去融入到Eclipse的种种机制中去。
这样做的另外一个坏处就是很难进行单元测试,比如脱离eclipse平台,使用一些mock类来进行简单有效的单元测试。
我在这方面也进行了一些尝试——”反客为主”,将必须遵守eclipse的回调要求变为必须遵守业务开发简单快捷的要求。同样是在progressMonitor上面,使用工厂类来创建delegate,然后可以在回调机制的外部向调用javaBean一样来使用平台给我们提供的这个功能。
这种尝试是有一定难度的,要使用到不同的设计模式,处理各种线程问题。更重要的一点是eclipse平台本身有这样的潜力,它也在等待着我们这样做。
4. 使用Flow规范插件项目开发
我的scoop项目最终搁浅,到最后我发现实现它已经超出了我当时的能力。我原本是想开发一个统一的插件开发及部署平台。这样很多中小软件企业,特别是像我原来工作的那家公司就可以拥有自己的eclipse插件集,以适应自己特殊的要求。我还想提供一套面向插件开发业务的接口,而不再面向技术也屏蔽各种技术细节,使得可以非常方便的扩展、修改甚至移植插件。我只是心里有想念就去实现而已,当最终认识到它有多么困难的时候不得不放弃了。最后虽然失败了,但并不觉得气馁。因为知道了要努力的方向,同时也积累了丰富的经验。最后就将这个jar包命名为SCOOP已示纪念。
演示文档及框架JAR包如下
/Files/jonenine/Eclipse_Dynamic_Classload.rar