缓存在Struts2中起到了重要的作用,Struts2中使用缓存来进行延迟加载。
[构成缓存的类和数据结构]
构成缓存的类主要是两个类,在com.opensymphony.xwork2.inject.util包中,分别是ReferenceMap<K,V>和ReferenceCache<K,V>,其中前者是后者的父类。说起来,这两个类并没有构成一个完整的缓存系统,它还留有一个create接口,用于供使用方来进行扩展。它们只是构成了一个大体的缓存框架,但对于缓存中值缺失的处理,就留待客户自己解决。ReferenceMap中采用一个ConcurrentMap来存储key-value对数字,考虑到一些特殊引用类型(WeakReference、SoftReference)的存在对数据读取和解析的影响,因此还需要两个变量指示key和value引用类型。在ReferenceMap中与存储相关的变量如下,这也是ReferenceMap类中声明的全部的实例变量:
transient
ConcurrentMap<Object, Object>
delegate
;
final
ReferenceType
keyReferenceType
;
final
ReferenceType
valueReferenceType
;
delegate是真正缓存数据的地方,keyReferenceType指示key的引用类型,valueReferenceType指示value的引用类型,ReferenceType是一个枚举类型的类。Struts2的缓存支持的引用类型数据包括:强引用(STRONG)、弱引用(WEAK)、软引用(SOFT),最后一种幽灵引用(PHANTON)并不支持。强引用是只要被引用的对象可达,就不会被垃圾回收;弱引用是被引用的对象随时可能会被垃圾回收;软引用是当虚拟机出现内存不足时会被垃圾回收以释放内存空间。
由于在缓存中存在多种不同的引用类型,因此在解析数据的时候需要考虑到多种不同引用的情况:
1、强引用类型,数据直接使用即可
2、弱引用或软引用类型,需要对缓存的数据进行一定的封装,使之按照设定的引用类型存储
在ReferenceMap类中给出了相应的接口,对key进行包装的是referenceKey方法,对value进行包装的是referenceValue方法,分别如下
Object referenceKey(K key) {
switch
(
keyReferenceType
) {
case
STRONG
:
return
key;
case
SOFT
:
return
new
SoftKeyReference(key);
case
WEAK
:
return
new
WeakKeyReference (key);
default
:
throw
new
AssertionError();
}
}
在对value进行引用包装的时候,要同时保存与之对应的key的值
Object referenceValue(Object keyReference, Object value) {
switch
(
valueReferenceType
) {
case
STRONG
:
return
value;
case
SOFT
:
return
new
SoftValueReference(keyReference, value);
case
WEAK
:
return
new
WeakValueReference(keyReference, value);
default
:
throw
new
AssertionError();
}
}
与之对应,在获取缓存数据时,也需要对数据进行解引用操作,强引用的对象直接使用,弱引用则需获取被引用的对象。解引用的方法是dereference,具体的代码如下