Struts2源码阅读(六)_ActionProxyActionInvocation
生活随笔
收集整理的這篇文章主要介紹了
Struts2源码阅读(六)_ActionProxyActionInvocation
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
下面開始講一下主菜ActionProxy了.在這之前最好先去了解一下動態Proxy的基本知識.
ActionProxy是Action的一個代理類,也就是說Action的調用是通過ActionProxy實現的,其實就是調用了ActionProxy.execute()方法,而該方法又調用了ActionInvocation.invoke()方法。歸根到底,最后調用的是DefaultActionInvocation.invokeAction()方法。
DefaultActionInvocation()->init()->createAction()。?
最后通過調用ActionProxy.exute()-->ActionInvocation.invoke()-->Intercepter.intercept()-->ActionInvocation.invokeActionOnly()-->invokeAction()
ActionProxy是Action的一個代理類,也就是說Action的調用是通過ActionProxy實現的,其實就是調用了ActionProxy.execute()方法,而該方法又調用了ActionInvocation.invoke()方法。歸根到底,最后調用的是DefaultActionInvocation.invokeAction()方法。
DefaultActionInvocation()->init()->createAction()。?
最后通過調用ActionProxy.exute()-->ActionInvocation.invoke()-->Intercepter.intercept()-->ActionInvocation.invokeActionOnly()-->invokeAction()
這里的步驟是先由ActionProxyFactory創建ActionInvocation和ActionProxy.
public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map<String, Object> extraContext, boolean executeResult, boolean cleanupContext) { ActionInvocation inv = new DefaultActionInvocation(extraContext, true); container.inject(inv); return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext); }
下面先看DefaultActionInvocation的init方法
public void init(ActionProxy proxy) { this.proxy = proxy; Map<String, Object> contextMap = createContextMap(); // Setting this so that other classes, like object factories, can use the ActionProxy and other // contextual information to operate ActionContext actionContext = ActionContext.getContext(); if (actionContext != null) { actionContext.setActionInvocation(this); } //創建Action,struts2中每一個Request都會創建一個新的Action createAction(contextMap); if (pushAction) { stack.push(action); contextMap.put("action", action); } 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<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors()); interceptors = interceptorList.iterator(); } protected void createAction(Map<String, Object> contextMap) { // load action String timerKey = "actionCreate: " + proxy.getActionName(); try { UtilTimerStack.push(timerKey); //默認為SpringObjectFactory:struts.objectFactory=spring.這里非常巧妙,在struts.properties中可以重寫這個屬性 //在前面BeanSelectionProvider中通過配置文件為ObjectFactory設置實現類 //這里以Spring為例,這里會調到SpringObjectFactory的buildBean方法,可以通過ApplicationContext的getBean()方法得到Spring的Bean action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap); } catch (InstantiationException e) { throw new XWorkException("Unable to intantiate Action!", e, proxy.getConfig()); } catch (IllegalAccessException e) { throw new XWorkException("Illegal access to constructor, is it public?", e, proxy.getConfig()); } catch (Exception e) { ... } finally { UtilTimerStack.pop(timerKey); } if (actionEventListener != null) { action = actionEventListener.prepare(action, stack); } } //SpringObjectFactory public Object buildBean(String beanName, Map<String, Object> extraContext, boolean injectInternal) throws Exception { Object o = null; try { //SpringObjectFactory會通過web.xml中的context-param:contextConfigLocation自動注入ClassPathXmlApplicationContext o = appContext.getBean(beanName); } catch (NoSuchBeanDefinitionException e) { Class beanClazz = getClassInstance(beanName); o = buildBean(beanClazz, extraContext); } if (injectInternal) { injectInternalBeans(o); } return o; }
private void executeResult() throws Exception { //根據ResultConfig創建Result result = createResult(); String timerKey = "executeResult: " + getResultCode(); try { UtilTimerStack.push(timerKey); if (result != null) { //開始執行Result, //可以參考Result的實現,如用了比較多的ServletDispatcherResult,ServletActionRedirectResult,ServletRedirectResult result.execute(this); } else if (resultCode != null && !Action.NONE.equals(resultCode)) { throw new ConfigurationException("No result defined for action " + getAction().getClass().getName() + " and result " + getResultCode(), proxy.getConfig()); } else { if (LOG.isDebugEnabled()) { LOG.debug("No result returned for action " + getAction().getClass().getName() + " at " + proxy.getConfig().getLocation()); } } } finally { UtilTimerStack.pop(timerKey); } } public Result createResult() throws Exception { //如果Action中直接返回的Result類型,在invokeAction()保存在explicitResult if (explicitResult != null) { Result ret = explicitResult; explicitResult = null; return ret; } //返回的是String則從config中得到當前Action的Results列表 ActionConfig config = proxy.getConfig(); Map<String, ResultConfig> results = config.getResults(); ResultConfig resultConfig = null; synchronized (config) { try { //通過返回的String來匹配resultConfig resultConfig = results.get(resultCode); } catch (NullPointerException e) { // swallow } if (resultConfig == null) { // If no result is found for the given resultCode, try to get a wildcard '*' match. //如果找不到對應name的ResultConfig,則使用name為*的Result //說明可以用*通配所有的Result resultConfig = results.get("*"); } } if (resultConfig != null) { try { //創建Result return objectFactory.buildResult(resultConfig, invocationContext.getContextMap()); } catch (Exception e) { LOG.error("There was an exception while instantiating the result of type " + resultConfig.getClassName(), e); throw new XWorkException(e, resultConfig); } } else if (resultCode != null && !Action.NONE.equals(resultCode) && unknownHandlerManager.hasUnknownHandlers()) { return unknownHandlerManager.handleUnknownResult(invocationContext, proxy.getActionName(), proxy.getConfig(), resultCode); } return null; } public Result buildResult(ResultConfig resultConfig, Map<String, Object> extraContext) throws Exception { String resultClassName = resultConfig.getClassName(); Result result = null; if (resultClassName != null) { //buildBean中會用反射機制Class.newInstance來創建bean result = (Result) buildBean(resultClassName, extraContext); Map<String, String> params = resultConfig.getParams(); if (params != null) { for (Map.Entry<String, String> paramEntry : params.entrySet()) { try { //reflectionProvider參見OgnlReflectionProvider; //resultConfig.getParams()就是result配置文件里所配置的參數<param></param> //setProperties方法最終調用的是Ognl類的setValue方法 //這句其實就是把param名值設置到根對象result上 reflectionProvider.setProperty(paramEntry.getKey(), paramEntry.getValue(), result, extraContext, true); } catch (ReflectionException ex) { if (LOG.isErrorEnabled()) LOG.error("Unable to set parameter [#0] in result of type [#1]", ex, paramEntry.getKey(), resultConfig.getClassName()); if (result instanceof ReflectionExceptionHandler) { ((ReflectionExceptionHandler) result).handle(ex); } } } } } return result; } 最后看一張在網上看到的一個調用流程圖作為參考:
總結
以上是生活随笔為你收集整理的Struts2源码阅读(六)_ActionProxyActionInvocation的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java并发编程实战~原子类
- 下一篇: javascript 数字精度问题