Nutz寻宝: 万能充电器-Nutz.Plugin

想了解更多,猛击[url]http://nutzhome.appspot.com/[/url]

原创者: zozoh [url]http://zozoh.iteye.com/[/url]

什么是插件

如果我们的项目依赖了一个接口,但是我们在开发时,真的没办法确定,部署的时候,到底采用哪个实现。

比如 Nutz.Log。 它在运行时,会判读当前运行环境 log4j 是否可用(有 log4j 的类,以及有 log4j 的配置文件),如果没有,它就检测 java.util.logging 是否可以用(有有效的配置文件),如果还没有,那么它就把日志信息输出到控制台上。它的实现,就是依靠的方式。

但是,同复杂强大的 OSGI 插件体系不同,这里的插件只是强调,在部署时决定采用什么实现。在运行时,它是没办法更改的。因此 Nutz 虽然在编译时依赖了 Log4j,但是在运行时,没有 log4j 的 jar,依然能够工作的很好。

也正因为,这个插件简单的令人发指。有兴趣的同学可以参看:
[url]http://code.google.com/p/nutz/source/browse/#svn/trunk/src/org/nutz/plugin[/url] 里面的源代码,我想几分钟你就会全部看完。
--------------------------------------------------------------------------------------------------------
简单使用插件
比如有一个接口:

public interface Said{
String say();
}

你有两个实现类:
* 实现类 A

public class TomSaid implements Said{
public String say(){
return "I am Tom";
}
}

* 实现类 B

public class PeterSaid implements Said{
public String say(){
return "I am Peter";
}
}

这两个实现类分别放在两个 jar 包里,在你的工程部署时,负责部署的工程师很希望:
* 将 tom.jar 放到项目里,整个工程就会使用 TomSaid,
* 将 peter.jar 放到项目,整个工程就会使用 PeterSaid,
* 将两个 jar 都放到项目,PeterSaid 有更高的优先级

{#A31;*怎样做到这一点呢?}

首先我们需要在你的工程里为 TomSaid 实现一个插件:

public class TomSaidPlugin implements Plugin, Said{
private Said said;
public boolean canWork(){
try {
said = (Said)(Class.forName("com.you.app.TomSaid").newInstance());
return true;
} catch (Exception e) {}
return false;
}
public String say(){
return said.say();
}
}


同理,为 PeterSaid 也实现一个插件:

public class PeterSaidPlugin implements Plugin, Said{
private Said said;
public boolean canWork(){
try {
said = (Said)(Class.forName("com.you.app.PeterSaid").newInstance());
return true;
} catch (Exception e) {}
return false;
}
public String say(){
return said.say();
}
}


在调用代码里这样实现:

PluginManager<Said> plugins = new SimplePluginManager<Said>(
"com.you.app.PeterSaidPlugin",
"com.you.app.TomSaidPlugin");
Said said = plugins.get();
System.out.println(said.say());

上面的代码既不依赖 PeterSaid,也不依赖 TomSaid,完全能满足部署工程师的要求。

采用 SimplePluginManager 有几个注意事项:
* 插件实现类必须有一个默认的构造函数
* 插件实现类必须实现目标接口,在上例中就是 Said 接口
* 插件实现类实际上就是一个被适配目标的一个代理 (在这里,你可以套套“代理模式”)
* 构造函数参数的顺序,就是插件的优先级,第一个最优先

--------------------------------------------------------------------------------------------------------

最后一点说明
我曾一度怀疑这个插件功能很无聊,因为它真的可以用“简陋”二字来形容(我们实现这个插件用的时间还没有我写这篇文档所用时间的一半),但是它毕竟给了你一条很简明的途径,让你的程序可以做到:

[color=red]部署时才决定某一个接口的实现[/color]

你用微小的代价(实现一个接口函数)获得下面两个好处:
* 你的应用很容易做到 [color=red]模块化[/color]
* 它几乎 [color=red]没有侵入性[/color]
挺值得的,不是吗? 这也是为什么我们将它放到 Nutz 的核心发布包里原因:
({/超值的东西才会被放到 Nutz 的核心包里})

如果你想做到运行时加载/卸载,这个“简陋”的小插件方案恐怕是帮不上你了。但是你真的需要吗?
我注意到一个事实:Eclipse 采用的是 “OSGI”,但是在安装了一个插件之后它还是会建议你重启应用,每次我看到这个对话框,都觉得是对 “OSGI” 的一个讽刺。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值