ActionInvocation实现分析

ActionInvocation是ActionProxy中非常重要的变量。在产生ActionProxy之后,调用proxy.prepare()来产生ActionInvocation的实例。
从ActionInvocation类的说明中,我们可以看到ActionInvocation包括拦截器和Action的实例。
An ActionInvocation represents the execution state of an Action. It holds the Interceptors and the Action instance. By repeated re-entrant execution of the invoke() method, initially by the ActionProxy, then by the Interceptors, the Interceptors are all executed, and then the Action and the Result.
那么他们是怎么实现的呢?来分析DefaultActionInvocation
DefaultActionInvocation包括如下的域:
    protected Object action;//Object getAction()
    protected ActionProxy proxy;//ActionProxy getProxy()
    protected List preResultListeners;//void addPreResultListener(PreResultListener listener)
    protected Map extraContext;
    protected ActionContext invocationContext;
    protected Iterator interceptors;
    protected ValueStack stack;//ValueStack getStack();
    protected Result result;//Result getResult()
    protected String resultCode;//String getResultCode()
    protected boolean executed = false;//boolean isExecuted();
    protected boolean pushAction = true;
    protected ObjectFactory objectFactory;
    protected ActionEventListener actionEventListener;//void setActionEventListener(ActionEventListener listener)

    protected UnknownHandler unknownHandler;

不能从域中直接得到的接口方法是:
String invoke() throws Exception;
String invokeActionOnly() throws Exception;

在它的构造器中
/**
在构造器的参数列表中,只有proxy能比较明确知道它的含义。
*/
protected DefaultActionInvocation(final ObjectFactory objectFactory, final UnknownHandler handler, final ActionProxy proxy, final Map extraContext, final boolean pushAction, final ActionEventListener actionEventListener) throws Exception {
    	UtilTimerStack.profile("create DefaultActionInvocation: ", 
    			new UtilTimerStack.ProfilingBlock<Object>() {
					public Object doProfiling() throws Exception {
						DefaultActionInvocation.this.proxy = proxy;
                        DefaultActionInvocation.this.objectFactory = objectFactory;
				        DefaultActionInvocation.this.extraContext = extraContext;
				        DefaultActionInvocation.this.pushAction = pushAction;
                        DefaultActionInvocation.this.unknownHandler = handler;
                        DefaultActionInvocation.this.actionEventListener = actionEventListener;
                        init();
						return null;
					}
    			});
    }


再来看init()方法:

private void init() throws Exception {
        [//把extraContext放入contextMap,并把DefaultActionInvocation本身也放到contextMap中。还有对stack域的赋值。如果extraContext不存在ValueStack,则新产生一个。http://dl.iteye.com/upload/attachment/479236/fa9d2253-5ad4-3400-bb4f-b2a42cc91861.png
        Map contextMap = createContextMap();
        //主要是利用传递进来的objectFactory来产生Action实例。objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap); 这个方法生成proxy.getConfig().getClassName()的实例,并把contextMap inject到其中。 inject的实现没看懂 http://dl.iteye.com/upload/attachment/479248/1ee39aa5-5898-3508-a818-5b4fac28fab2.png
        createAction(contextMap);
        //如果需要向stack中推入action实例,则推入。
        if (pushAction) {
            stack.push(action);
        }
        //ActionContext其实就是一map,核心就只有Map context;其它就是定义的编译时常量和一个管理各个线程的ActionContext的实例的静态ThreadLocal域。
        invocationContext = new ActionContext(contextMap);
        invocationContext.setName(proxy.getActionName());

        // get a new List so we don't get problems with the iterator if someone changes the list
        List interceptorList = new ArrayList(proxy.getConfig().getInterceptors());
        interceptors = interceptorList.iterator();
    }


再来看一个这个类的核心invoke()方法:
    public String invoke() throws Exception {
    	String profileKey = "invoke: ";
    	try {
    		UtilTimerStack.push(profileKey);
    		
    		if (executed) {
    			throw new IllegalStateException("Action has already executed");
    		}

    		if (interceptors.hasNext()) {
    			final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
    			UtilTimerStack.profile("interceptor: "+interceptor.getName(), 
    					new UtilTimerStack.ProfilingBlock<String>() {
							public String doProfiling() throws Exception {
				    			resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
				    			return null;
							}
    			});
    		} else {
                        //在调用完所有Interceptor之后,调用此。即invokeAction(getAction(), proxy.getConfig());又即method.invoke(action,new Object[0]);
    			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
    		if (!executed) {
    			if (preResultListeners != null) {
    				for (Iterator iterator = preResultListeners.iterator();
    					iterator.hasNext();) {
    					PreResultListener listener = (PreResultListener) iterator.next();
    					
    					String _profileKey="preResultListener: ";
    					try {
    						UtilTimerStack.push(_profileKey);
    						listener.beforeResult(this, resultCode);
    					}
    					finally {
    						UtilTimerStack.pop(_profileKey);
    					}
    				}
    			}

    			// now execute the result, if we're supposed to
    			if (proxy.getExecuteResult()) {
    				executeResult();
    			}

    			executed = true;
    		}

    		return resultCode;
    	}
    	finally {
    		UtilTimerStack.pop(profileKey);
    	}
    }

猜你喜欢

转载自jfar.iteye.com/blog/1040141
今日推荐