1.1.1 ActionInvocation類
ActionInvocation定義為一個接口。主要作用是表現action的運行狀態。它擁有攔截器和action的實例。通過重復的運行invoke方法。首先被actionProxy,然后是攔截器,全部攔截器運行完后就是action和result .

圖3.3.4 ActionInvocation類的主要方法
1.1.2 DefaultActionInvocation類
DefaultActionInvocation類是ActionInvocation接口的實現類. 一般都用該類實例化ActionInvocation。 基本的方法例如以下:

圖3.3.5 DefaultActionInvocation類的主要方法
關鍵方法:invoke()方法
executed = false; 默覺得false。表示該action還沒有運行。
假設運行就會拋出已經運行的異常。
然后推斷攔截器是否已經配置,假設配置了攔截器就會從配置信息中獲得攔截器配置類InterceptorMapping。
此類中僅僅包括兩個屬性,一個就是name和interceptor實例。
public String invoke() throws Exception {
String profileKey = "invoke: ";
try {
UtilTimerStack.push(profileKey);
if (executed) {
throw new IllegalStateException("Action has already executed");
}
//遞歸運行interceptor
if (interceptors.hasNext())
{ //interceptors是InterceptorMapping實際上是像一個像//FilterChain一樣的Interceptor鏈
//通過調用Invocation.invoke()實現遞歸牡循環
final InterceptorMapping interceptor = interceptors.next();
String interceptorMsg = "interceptor: " + interceptor.getName();
UtilTimerStack.push(interceptorMsg);
try {
//在每一個Interceptor的方法中都會return invocation.invoke()
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
}
finally {
UtilTimerStack.pop(interceptorMsg);
}
} else {
//當全部interceptor都運行完,最后運行Action,invokeActionOnly會調用//invokeAction()方法
resultCode = invokeActionOnly();
}
|
|
// this is needed because the result will be executed, then control will return to the Interceptor, which will
// return above and flow through again
//在Result返回之前調用preResultListeners
//通過executed控制,僅僅運行一次
if (!executed) {
if (preResultListeners != null) {
for (Object preResultListener : preResultListeners) {
PreResultListener listener = (PreResultListener) preResultListener;
String _profileKey = "preResultListener: ";
try {
UtilTimerStack.push(_profileKey);
listener.beforeResult(this, resultCode);
}
finally {
UtilTimerStack.pop(_profileKey);
}
}
}
// now execute the result, if we're supposed to
//運行result。
if (proxy.getExecuteResult()) {
executeResult();
}
executed = true;
}
return resultCode;
}
finally {
UtilTimerStack.pop(profileKey);
}
}
|
|