服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

用java动态代理类实现记忆功能

ad_qqread_mid_big">
  通过动态代理类来创建一个通用的缓存包装器

  上面第二种方法仅有的缺点就是缓存包装器不能重用,每次我们希望添加一个缓存给某个类,我们就要写一个特殊的缓存包装器给目标接口.这是一个很慢,容易出错的过程.

  jdk1.3开始支持动态代理类: 特别的类能够在运行期决定实现哪个接口-通常的模式都是,在运行期即决定实现哪个接口.通过这个,我们有可能实现一个通用的缓存包装器,我们称它为memoizer,在运行期决定实现哪个接口.这样, cachingbinarydigitscalculator就是不再需要的.它是这样被调用的:

binarydigitscalculator calculator =
new cachingbinarydigitscalculator(
new pibinarydigitscalculator()
);

  可以通过memoizer来重写如下:

binarydigitscalculator calculator =
(binarydigitscalculator) memoizer.memoize(
new pibinarydigitscalculator()
);

memoizer的代码如下:
import java.lang.reflect.invocationhandler;
import java.lang.reflect.invocationtargetexception;
import java.lang.reflect.method;
import java.lang.reflect.proxy;
import java.util.arrays;
import java.util.collections;
import java.util.hashmap;
import java.util.list;
import java.util.map;

public class memoizer implements invocationhandler {
public static object memoize(object object) {
return proxy.newproxyinstance(
object.getclass().getclassloader(),
object.getclass().getinterfaces(),
new memoizer(object)
);
}

private object object;
private map caches = new hashmap();

private memoizer(object object) {
this.object = object;
}

public object invoke(object proxy, method method,
object[] args) throws throwable {

if (method.getreturntype().equals(void.type)) {
// don't cache void methods
return invoke(method, args);
} else {
map cache = getcache(method);
list key = arrays.aslist(args);
object value = cache.get(key);

if (value == null && !cache.containskey(key)) {
value = invoke(method, args);
cache.put(key, value);
}
return value;
}
}

private object invoke(method method, object[] args)
throws throwable {
try {
return method.invoke(object, args);
} catch (invocationtargetexception e) {
throw e.gettargetexception();
}
}

private synchronized map getcache(method m) {
map cache = (map) caches.get(m);
if (cache == null) {
cache = collections.synchronizedmap(
new hashmap()
);
caches.put(m, cache);
}
return cache;
}
}

  当调用静态方法memoize的时候,将会创建一个新的代理实例-也就是一个java.lang.reflect.proxy的实例.实现了一个接口集.这个接口集由object.getclass().getinterfaces()来决定.每个代理实例包含一个java.lang.reflect.invocationhandler实例来处理这个代理实例调用的相关方法.在我们的例子里,memoizer就是一个invocationhandler实例.

  当一个方法在代理实例里被调用,比如, calculatebinarydigit,那么, memoizer实例里的invoke方法就会被调用,相关信息会传给invoke方法,以决定proxy实例调用了哪个方法,包含参数信息.在我们的例子里,传入memoizer的java.lang.method参数是calculatebinarydigit,而参数信息则是pi需要精确的位数-整数n.在这个基础上,memoizer能够进一步进行缓存操作的.

  在例子里(caches是一个hashmap,cache是一个map)里用到的key,主要是传入的方法信息:method对象和参数对象. 为了实现的简单与通用性,memoizer有一个关于cache的hashmap caches,每个method是一个key,对应的value为一个cache.然后把参数信息转化成一个list对象,作为cache的key.使用list是很方便的,同时也可以保证equals()方法,所以能够保证当且仅当参数信息完全相同的时候这个list才相等.

  一旦一个cache的key被创建,那么,计算之前都会先查找这个cache,如果找到,则返回cache里的值.否则,如果带有这些参数的这个方法没有被调用过,那么,则会通过invoke来调用这个method.在我们的例子里, 实例pibinarydigitscalculator 里的calculatebinarydigit方法将会通过invoke被调用.而且计算结果将会被存在cache里. >>>更多专题请看java的类专题
上一页 1 2 3 4 下一页 
相关内容:设计  包装  python  perl  java  
【收藏此页】【大 中 小】【打印】【关闭】
上一篇:java设计模式之工厂方法模式
下一篇:基于eclipse开发轻量级spring插件


10万个软件免费高速下载
教育教学 安全相关 游戏娱乐 源码下载 编程开发 数码软件 其它类别
网络软件 联络聊天 系统工具 媒体工具 图形图像 应用软件 行业软件
·max粒子系统轻松实现群蝶飞舞
·轻松实现电脑一分为二:betwin
·实例讲解 用excel实现机打支票
·盗qq的密码软件模拟实现(vc)
·以假乱真 linux中实现vista界面
·用vc实现小型矢量图形系统的开发(上)
·用vb实现实时曲线的绘制和保存
·vc实现卡拉ok字幕叠加
·利用c#实现标注式消息提示窗口
·巧妙实现眼球影响眼皮的联动!
 
·接口和抽象类的定义方式举例说明
·用maven制作java项目发行包
·java 基础入门 pom.xml 元素描述
·用jbuilder2007开发扩展jsf标签的插
·抽象类对象类和对象包装类
·使用java实现在文件中添加字符串
·instanceof和回调概念
·java变量的赋值与传递
·java se6调用java编译器的两种新方法
·weblogic运用db的java控件访问数据库

扫描关注微信公众号