public class Element implements Serializable, Cloneable {
//the cache key. 从1.2以后不再强制要求Serializable,因为如果只是作为内存缓存,则不需要对它做序列化。IgnoreSizeOf注解表示在做SizeOf计算时key会被忽略。 @IgnoreSizeOf
private final Object key;
//the value. 从1.2以后不再强制要求Serializable,因为如果只是作为内存缓存,则不需要对它做序列化。 private final Object value;
//version of the element. 这个属性只是作为纪录信息,EHCache实际代码中并没有用到,用户代码可以通过它来实现不同版本的处理问题。默认值是1。//如果net.sf.ehcache.element.version.auto系统属性设置为true,则当Element加入到Cache中时会被更新为当前系统时间。此时,用户设置的值会丢失。 private volatile long version;
//The number of times the element was hit.命中次数,在每次查找到一个Element会加1。 private volatile long hitCount;
//The amount of time for the element to live, in seconds. 0 indicates unlimited. 即一个Element自创建(CreationTime)以后可以存活的时间。 private volatile int timeToLive = Integer.MIN_VALUE;
//The amount of time for the element to idle, in seconds. 0 indicates unlimited. 即一个Element自最后一次被使用(min(CreationTime,LastAccessTime))以后可以存活的时间。 private volatile int timeToIdle = Integer.MIN_VALUE;
//Pluggable element eviction data instance,它存储这个Element的CreationTime、LastAccessTime等信息,窃以为这个抽取成一个单独的类没什么理由,而且这个类的名字也不好。 private transient volatile ElementEvictionData elementEvictionData;
//If there is an Element in the Cache and it is replaced with a new Element for the same key,//then both the version number and lastUpdateTime should be updated to reflect that. The creation time//will be the creation time of the new Element, not the original one, so that TTL concepts still work. 在put和replace操作中该属性会被更新。 private volatile long lastUpdateTime;
//如果timeToLive和timeToIdle没有手动设置,该值为true,此时在计算expired时使用CacheConfiguration中的timeTiLive、timeToIdle的值,否则使用Element自身的值。 private volatile boolean cacheDefaultLifespan = true;
//这个ID值用于EHCache内部,但是暂时不知道怎么用。 private volatile long id = NOT_SET_ID;
//判断是否expired,这里如果timeToLive、timeToIdle都是Integer.MIN_VALUE时返回false,当他们都是0时,isEternal返回true public boolean isExpired() {
if (!isLifespanSet() || isEternal()) {
return false;
}
long now = System.currentTimeMillis();
long expirationTime = getExpirationTime();
return now > expirationTime;
}
//expirationTime算法:如果timeToIdle没有设置,或设置了,但是该Element还没有使用过,取timeToLive计算出的值;如果timeToLive没有设置,则取timeToIdle计算出的值,//否则,取他们的最小值。 public long getExpirationTime() {
if (!isLifespanSet() || isEternal()) {
return Long.MAX_VALUE;
}
long expirationTime = 0;
long ttlExpiry = elementEvictionData.getCreationTime() + TimeUtil.toMillis(getTimeToLive());
long mostRecentTime = Math.max(elementEvictionData.getCreationTime(), elementEvictionData.getLastAccessTime());
long ttiExpiry = mostRecentTime + TimeUtil.toMillis(getTimeToIdle());
if (getTimeToLive() != 0 && (getTimeToIdle() == 0 || elementEvictionData.getLastAccessTime() == 0)) {
expirationTime = ttlExpiry;
} else if (getTimeToLive() == 0) {
expirationTime = ttiExpiry;
} else {
expirationTime = Math.min(ttlExpiry, ttiExpiry);
}
return expirationTime;
}
//在将Element加入到Cache中并且它的timeToLive和timeToIdle都没有设置时,它的timeToLive和timeToIdle会根据CacheConfiguration的值调用这个方法更新。 protected void setLifespanDefaults(int tti, int ttl, boolean eternal) {
if (eternal) {
this.timeToIdle = 0;
this.timeToLive = 0;
} else if (isEternal()) {
this.timeToIdle = Integer.MIN_VALUE;
this.timeToLive = Integer.MIN_VALUE;
} else {
timeToIdle = tti;
timeToLive = ttl;
}
}
}
public class DefaultElementEvictionData implements ElementEvictionData {
private long creationTime;
private long lastAccessTime;
}
public class Cache implements InternalEhcache, StoreListener {
private void applyDefaultsToElementWithoutLifespanSet(Element element) {
if (!element.isLifespanSet()) {
element.setLifespanDefaults(TimeUtil.convertTimeToInt(configuration.getTimeToIdleSeconds()),
TimeUtil.convertTimeToInt(configuration.getTimeToLiveSeconds()),
configuration.isEternal());
}
}
}