ActionContext:
public class ActionContext implements Serializable {
static ThreadLocal actionContext = new ThreadLocal();//补充本质上就是一个ThreadLocal将当前thread与entryT绑定
/**
* Constant for the name of the action being executed.
*/
public static final String ACTION_NAME = "com.opensymphony.xwork2.ActionContext.name";
/**
* Constant for the {@link com.opensymphony.xwork2.util.ValueStack OGNL value stack}.
*/
public static final String VALUE_STACK = ValueStack.VALUE_STACK;//其中
/**
* Constant for the action's session.
*/
public static final String SESSION = "com.opensymphony.xwork2.ActionContext.session";
/**
* Constant for the action's application context.
*/
public static final String APPLICATION = "com.opensymphony.xwork2.ActionContext.application";
/**
* Constant for the action's parameters.
*/
public static final String PARAMETERS = "com.opensymphony.xwork2.ActionContext.parameters";
/**
* Constant for the action's locale.
*/
public static final String LOCALE = "com.opensymphony.xwork2.ActionContext.locale";
/**
* Constant for the action's type converter.
*/
public static final String TYPE_CONVERTER = "com.opensymphony.xwork2.ActionContext.typeConverter";
/**
* Constant for the action's {@link com.opensymphony.xwork2.ActionInvocation invocation} context.
*/
public static final String ACTION_INVOCATION = "com.opensymphony.xwork2.ActionContext.actionInvocation";
/**
* Constant for the map of type conversion errors.
*/
public static final String CONVERSION_ERRORS = "com.opensymphony.xwork2.ActionContext.conversionErrors";
/**
* Constant for the container
*/
public static final String CONTAINER = "com.opensymphony.xwork2.ActionContext.container";
private Map context;//将不同的域统一管理
如何统一管理:
//以setSession为例
public void setSession(Map
put(SESSION, session);
}
public void put(String key, Object value) {
context.put(key, value);
}
OgnlValueStack(valueStack)
public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack {
public static final String THROW_EXCEPTION_ON_FAILURE = OgnlValueStack.class.getName() + ".throwExceptionOnFailure";
private static final long serialVersionUID = 370737852934925530L;
private static final String MAP_IDENTIFIER_KEY = "com.opensymphony.xwork2.util.OgnlValueStack.MAP_IDENTIFIER_KEY";
private static final Logger LOG = LoggerFactory.getLogger(OgnlValueStack.class);
CompoundRoot root;//
transient Map context;//context(即为ActionContext):
如何保证ActionContext线程安全:
public static ActionContext getContext() {
//获取当前线程绑定的ActionContext对象
return actionContext.get();
}
简述: Thread, ThreadLocal, ThreadLocalMap关系
//Thread下有个ThreadLocal.ThreadLocalMap threadlocals
//从上可看出ThreadLocal中有个静态类ThreadLocalMap..
获取value(ThreadLocal绑定的object:value)简述:
1.ThreadLocal中通过t.threadlocals获取tm
2.而ThreadLocalMap又通过ThreadLocal查询value
误区:ThreadLocalMap并非为简单的Map
而是一个size+1的数组..
public class ThreadLocal
static class ThreadLocalMap {
/**
* The table, resized as necessary.
* table.length MUST always be a power of two.
*/
private Entry[] table;
private void set(ThreadLocal key, Object value) {
// We don't use a fast path as with get() because it is at
// least as common to use set() to create new entries as
// it is to replace existing ones, in which case, a fast
// path would fail more often than not.
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
ThreadLocal k = e.get();
//如果已经存在就直接return
if (k == key) {
e.value = value;
return;
}
if (k == null) {
replaceStaleEntry(key, value, i);
return;
}
}
//不存在就new添加进数组或者
tab[i] = new Entry(key, value);
int sz = ++size;//后续步骤猜测:添加一个null进数组
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}