root 对象
CompoundRoot, CompoundRoot扩展了ArrayList,具有容纳对象及后进先出类似“栈”的能力。
public class CompoundRoot extends ArrayList {
public CompoundRoot() {
}
public CompoundRoot(List list) {
super(list);
}
public CompoundRoot cutStack(int index) {
return new CompoundRoot(subList(index, size()));
}
public Object peek() {
return get(0);
}
public Object pop() {
return remove(0);
}
public void push(Object o) {
add(0, o);
}
}
(不明白为啥用0做栈顶呢?ArrayList 每次push 或remove 之后都需要重建数组)
CompoundRoot中元素的添加及提取:
OgnlValueStack提供的peek,pop,push 方法,从root中提取元素或添加元素:
- /**
- * @see com.opensymphony.xwork2.util.ValueStack#peek()
- */
- public Object peek() {
- return root.peek();
- }
- /**
- * @see com.opensymphony.xwork2.util.ValueStack#pop()
- */
- public Object pop() {
- return root.pop();
- }
- /**
- * @see com.opensymphony.xwork2.util.ValueStack#push(java.lang.Object)
- */
- public void push(Object o) {
- root.push(o);
- }
通过表达式对CompoundRoot中元素的访问
CompoundRootAccessor 实现了对 CompoundRoot 中元素以表达式方式的访问,
CompoundRootAccessor类扩展了ognl的PropertyAccessor,MethodAccessor,ClassResolver
Ognl中的root对象一般是一个javabean或Map,通过表达式中指定的属性名或key,就可以定位到属性对象
CompoundRoot 是一个ArrayList,对于表达式中指定的属性,是ArrayList中哪一个元素的属性呢? 这就需要遍历每一个元素,进行判断。
以表达式方式对CompoundRoot 中元素的属性赋值(setProperty):
对 CompoundRoot 遍历,遍历顺序由栈顶到栈底,遍历的每一个元素,都当做ognl的root对象,判断是否存在指定的属性,如果存在则对该root对象的属性赋值,遍历中下一个元素是Map,则直接使用put 方法存属性和名称,就不继续查找了:
for (Object o : root) {//CompoudRoot是ArrayList,遍历内部所有对象
if (o == null) {
continue;
}
try {
if (OgnlRuntime.hasSetProperty(ognlContext, o, name)) {
OgnlRuntime.setProperty(ognlContext, o, name, value);
//当前元素有name属性,则调用ognl进行赋值
return;
} else if (o instanceof Map) {
Map<Object, Object> map = (Map) o;
try {
map.put(name, value);
return;//如果下一个元素是Map,则直接使用put方法存属性名和值
} catch (UnsupportedOperationException e) {
// This is an unmodifiable Map, so move on to the next element in the stack
}
}
}
以表达式方式对CompoundRoot 中元素的属性值的获值(getProperty):
对 CompoundRoot 遍历,遍历顺序由栈顶到栈底,遍历的每一个元素,都当做ognl的root对象,判断是否存在指定的属性,如果存在则获值属性值:
for (Object o : root) {//遍历
if (o == null) {
continue;
}
try {
if ((OgnlRuntime.hasGetProperty(ognlContext, o, name)) || ((o instanceof Map) && ((Map) o).containsKey(name))) {
return OgnlRuntime.getProperty(ognlContext, o, name);//当前元素有该属性,则获取
}
} catch (OgnlException e) {
if (e.getReason() != null) {
final String msg = "Caught an Ognl exception while getting property " + name;
throw new XWorkException(msg, e);
}
} catch (IntrospectionException e) {
// this is OK if this happens, we'll just keep trying the next
}
}
以表达式方式对CompoundRoot 中元素的方法调用(callMethod):
对 CompoundRoot 遍历,遍历顺序由栈顶到栈底,遍历的每一个元素,都当做ognl的root对象,对其调用指定的方法,如果返回值不为空,则说明正确,并返回方法返回值。
for (Object o : root) {//遍历
if (o == null) {
continue;
}
Class clazz = o.getClass();
Class[] argTypes = getArgTypes(objects);
MethodCall mc = null;
if (argTypes != null) {
mc = new MethodCall(clazz, name, argTypes);
}
if ((argTypes == null) || !invalidMethods.containsKey(mc)) {
try {
Object value = OgnlRuntime.callMethod((OgnlContext) context, o, name, name, objects);
if (value != null) {//返回值不为空,该元素上有此方法并调用成功
return value;
}
} catch (OgnlException e) {
// try the next one
Throwable reason = e.getReason();
if (!context.containsKey(OgnlValueStack.THROW_EXCEPTION_ON_FAILURE) && (mc != null) && (reason != null) && (reason.getClass() == NoSuchMethodException.class)) {
invalidMethods.put(mc, Boolean.TRUE);
} else if (reason != null) {
throw new MethodFailedException(o, name, e.getReason());
}
}
}
}
对 CompoundRoot 指定位置元素的访问:
1.top.属性名 (top 栈顶元素)
2.[index].top CompoundRoot 中的第N个元素[index]会调用 CompoundRoot.cutStack从第indedx位置开始的元素组成新的 CompoundRoot,top是栈顶元素