zcx

Java ClassLoader 实现程序的扩展性

  

今天在完成一个功能的时候,使用了ServiceLocate模式,

通过这个模式,在程序中可以自由的加载其他成员实现的功能模块

具体的做法:

 1)定义标准的服务接口。

 2)定义描述实现服务接口的xml文件。

 3)程序读取该xml文件,使用Class.newInstance()实例化具体的服务对象。

 4)建立一个特定服务和特定服务实现的对应的HashMap对象。完成注册任务。

 5)主程序中根据具体的服务从HashMap中取得具体的对象进行服务。

 

这个方法还不错,可以完成基于Interface的开发要求,利于Test和程序的拓展性。

有新的要求出现后,只需要添加xml中的元素和具体的实现类就可以了。

 

接下来,继续想。又发现了一些问题:

1)xml是和程序一起发布的,如果用户随意改动了。很明显程序会崩溃。

解决方法:xml放在jar包中,使用getClass().getResourceAsStream(String name)

自己加载进来。用户完全不知道具体的情况。

 

2)如果把xml放在了jar包中“藏起来”,实际上原来带来的动态扩展的特性,

也就没有那么明显了。如何解决呢

 

细细想来,这个问题的关键在于,所有的服务实例对象的创建和注册都是在

主控程序中通过xml来完成的。如果可以把这个注册和实例化的过程从主控程序

中分离出来,通过每个服务实例对象自动注册来完成,那么才算是真正的可拓展的。

如果需要完成新的功能,只需要把新的服务对象Class发布,重新运行主控程序就会实现新的功能。(看起来就和Eclipse一样)

这真是一个不错的想法,但是怎么做呢?

 

看看Eclipse如何做的。

http://www.eclipse.org/articles/Article-Plug-in-architecture/plugin_architecture.html

 

 

首先要有一个规定的plugin deploy目录,这样主程序才知道从哪里加载。

要有一个plugin.xml文件描述这个plugin.这着文件中有属性:class="foo.bar.Plugin">

看上去和我们原来做的方式一样啊。但是它是如何把这个目录下的plugin都加载的呢?

(我没有看过Eclipse的源码,不知道他是怎么写的)

 

再想想,其实主要要解决的问题是不通过主框架程序注册服务实现,

应该由服务程序自己注册上来。按照这个思路,我想有两种解决方案。

1)服务接口添加registerService 方法。

   * 在jar的METATINFO文件中定义类名。

   * 从特定的目录中读取jar/class文件。

   * 通过URLClassLoader.newInstance()加载

   * 加载后把ServiceLoader作为参数出入 service.registerSevice()中

   * service对象完成自己的注册。

2)服务添加static代码端在类被实例化的时候自动完成注册。

   * 加载之前和上一个方法一样。

   * 对SeviceLoader对象实现为单态的模式。提供静态的注册方法。

   * 在servie对象中实现如下的代码段完成自动注册。

   static

              {

                ServiceLoader.registerService(new service());

              }

 

 

这样看来总算OK了吧。

posted on 2005-01-11 18:00 zcx 阅读(695) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: