capture方法:抓取线程(线程A)的所有TTL值。
replay方法:在另一个线程(线程B)中,回放在capture方法中抓取的TTL值,并返回 回放前TTL值的备份
restore方法:恢复线程B执行replay方法之前的TTL值(即备份)
弄明白核心流程和原理后,我们现在来分析下相关核心代码,在声明TransmittableThreadLocal变量时,我们会发现框架初始化了一个类级别的变量holder用于存储用户设置的所有ttl上下文,也是为了后续执行capture抓取时使用。
// Note about the holder:
// 1. holder self is a InheritableThreadLocal(a ThreadLocal).
// 2. The type of value in the holder is WeakHashMap<TransmittableThreadLocal, ?>.
// 2.1 but the WeakHashMap is used as a Set:
// the value of WeakHashMap is always null, and never used.
// 2.2 WeakHashMap support null value.
private static final InheritableThreadLocal<WeakHashMap<TransmittableThreadLocal, ?>> holder =
new InheritableThreadLocal<WeakHashMap<TransmittableThreadLocal, ?>>() {
@Override
protected WeakHashMap<TransmittableThreadLocal, ?> initialValue() {
return new WeakHashMap<TransmittableThreadLocal, Object>();
}
@Override
protected WeakHashMap<TransmittableThreadLocal, ?> childValue(WeakHashMap<TransmittableThreadLocal, ?> parentValue) {
return new WeakHashMap<TransmittableThreadLocal, Object>(parentValue);
}
};
/**
- see {@link InheritableThreadLocal#set}
*/
@Override
public final void set(T value) {
if (!disableIgnoreNullValueSemantics && null == value) {
// may set null to remove value
remove();
} else {
super.set(value);
addThisToHolder();
}
}
private void addThisToHolder() {
if (!holder.get().containsKey(this)) {
holder.get().put((TransmittableThreadLocal) this, null); // WeakHashMap supports null value.
}
}
结合set方法实现来看,我们会发现holder变量设计的非常巧妙,业务设置的上下文value部分继续复用ThreadLocal原有数据结构ThreadLocalMap来存储( super.set(value));capture的数据源利用holder进行引用存储(addThisToHolder put this)。这样的好处是既可保持ThreadLocal数据存储原有的封装性,又很好实现扩展。除此之外,holder还有其他设计考究,这里抛出来大家可以思考下:
-
为什么holder需要设计成static final类级别变量?