Struts2源码阅读(六)_ActionProxy&ActionInvocation

下面开始讲一下主菜ActionProxy了.在这之前最好先去了解一下动态Proxy的基本知识.
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.

  1. 1public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map<String, Object> extraContext, boolean executeResult, boolean cleanupContext) {    
  2. 2.         
  3. 3.     ActionInvocation inv = new DefaultActionInvocation(extraContext, true);    
  4. 4.     container.inject(inv);    
  5. 5.     return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext);    
  6. 6. }    


 

先看DefaultActionInvocation的init方法

  1.  1public void init(ActionProxy proxy) {    
  2.  2.     this.proxy = proxy;    
  3.  3.     Map<String, Object> contextMap = createContextMap();    
  4.  4.     
  5.  5.     // Setting this so that other classes, like object factories, can use the ActionProxy and other    
  6.  6.     // contextual information to operate    
  7.  7.     ActionContext actionContext = ActionContext.getContext();    
  8.  8.     
  9.  9.     if (actionContext != null) {    
  10. 10.         actionContext.setActionInvocation(this);    
  11. 11.     }    
  12. 12.     //创建Action,struts2中每一个Request都会创建一个新的Action    
  13. 13.     createAction(contextMap);    
  14. 14.     
  15. 15.     if (pushAction) {    
  16. 16.         stack.push(action);    
  17. 17.         contextMap.put("action", action);    
  18. 18.     }    
  19. 19.     
  20. 20.     invocationContext = new ActionContext(contextMap);    
  21. 21.     invocationContext.setName(proxy.getActionName());    
  22. 22.     
  23. 23.     // get a new List so we don't get problems with the iterator if someone changes the list    
  24. 24.     List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(proxy.getConfig().getInterceptors());    
  25. 25.     interceptors = interceptorList.iterator();    
  26. 26. }    
  27. 27.         
  28. 28protected void createAction(Map<String, Object> contextMap) {    
  29. 29.     // load action    
  30. 30.     String timerKey = "actionCreate: " + proxy.getActionName();    
  31. 31.     try {    
  32. 32.         UtilTimerStack.push(timerKey);    
  33. 33.         //默认为SpringObjectFactory:struts.objectFactory=spring.这里非常巧妙,在struts.properties中可以重写这个属性    
  34. 34.         //在前面BeanSelectionProvider中通过配置文件为ObjectFactory设置实现类    
  35. 35.         //这里以Spring为例,这里会调到SpringObjectFactory的buildBean方法,可以通过ApplicationContext的getBean()方法得到Spring的Bean    
  36. 36.         action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap);    
  37. 37.     } catch (InstantiationException e) {    
  38. 38.         throw new XWorkException("Unable to intantiate Action!", e, proxy.getConfig());    
  39. 39.     } catch (IllegalAccessException e) {    
  40. 40.         throw new XWorkException("Illegal access to constructor, is it public?", e, proxy.getConfig());    
  41. 41.     } catch (Exception e) {    
  42. 42.        ...    
  43. 43.     } finally {    
  44. 44.         UtilTimerStack.pop(timerKey);    
  45. 45.     }    
  46. 46.     
  47. 47.     if (actionEventListener != null) {    
  48. 48.         action = actionEventListener.prepare(action, stack);    
  49. 49.     }    
  50. 50. }    
  51. 51//SpringObjectFactory    
  52. 52public Object buildBean(String beanName, Map<String, Object> extraContext, boolean injectInternal) throws Exception {    
  53. 53.     Object o = null;    
  54. 54.     try {    
  55. 55.         //SpringObjectFactory会通过web.xml中的context-param:contextConfigLocation自动注入ClassPathXmlApplicationContext    
  56. 56.         o = appContext.getBean(beanName);    
  57. 57.     } catch (NoSuchBeanDefinitionException e) {    
  58. 58.         Class beanClazz = getClassInstance(beanName);    
  59. 59.         o = buildBean(beanClazz, extraContext);    
  60. 60.     }    
  61. 61.     if (injectInternal) {    
  62. 62.         injectInternalBeans(o);    
  63. 63.     }    
  64. 64.     return o;    
  65. 65. }    


 

  1.   1//接下来看看DefaultActionInvocation 的invoke方法    
  2.   2public String invoke() throws Exception {    
  3.   3.     String profileKey = "invoke: ";    
  4.   4.     try {    
  5.   5.         UtilTimerStack.push(profileKey);    
  6.   6.        
  7.   7.         if (executed) {    
  8.   8.             throw new IllegalStateException("Action has already executed");    
  9.   9.         }    
  10.  10.         //递归执行interceptor    
  11.  11.         if (interceptors.hasNext()) {    
  12.  12.             //interceptors是InterceptorMapping实际上是像一个像FilterChain一样的Interceptor链    
  13.  13.             //通过调用Invocation.invoke()实现递归牡循环    
  14.  14.             final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();    
  15.  15.             String interceptorMsg = "interceptor: " + interceptor.getName();    
  16.  16.             UtilTimerStack.push(interceptorMsg);    
  17.  17.             try {      
  18.  18.                  //在每个Interceptor的方法中都会return invocation.invoke()           
  19.  19.                  resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);    
  20.  20.                 }    
  21.  21.             finally {    
  22.  22.                 UtilTimerStack.pop(interceptorMsg);    
  23.  23.             }    
  24.  24.         } else {      
  25.  25.             //当所有interceptor都执行完,最后执行Action,invokeActionOnly会调用invokeAction()方法    
  26.  26.             resultCode = invokeActionOnly();    
  27.  27.         }    
  28.  28.     
  29.  29.         // this is needed because the result will be executed, then control will return to the Interceptor, which will    
  30.  30.         // return above and flow through again      
  31.  31.         //在Result返回之前调用preResultListeners     
  32.  32.         //通过executed控制,只执行一次     
  33.  33.         if (!executed) {    
  34.  34.             if (preResultListeners != null) {     
  35.  35.                 for (Object preResultListener : preResultListeners) {     
  36.  36.                     PreResultListener listener = (PreResultListener) preResultListener;    
  37.  37.                                                                     
  38.  38.                     String _profileKey = "preResultListener: ";     
  39.  39.                     try {                                           
  40.  40.                         UtilTimerStack.push(_profileKey);                                 
  41.  41.                         listener.beforeResult(this, resultCode);    
  42.  42.                     }                                               
  43.  43.                     finally {                                       
  44.  44.                         UtilTimerStack.pop(_profileKey);            
  45.  45.                     }                                               
  46.  46.                 }                                                   
  47.  47.             }                                                       
  48.  48.                                                                     
  49.  49.             // now execute the result, if we're supposed to         
  50.  50.             //执行Result                                            
  51.  51.             if (proxy.getExecuteResult()) {                         
  52.  52.                 executeResult();                                    
  53.  53.             }                                                       
  54.  54.                                                                     
  55.  55.             executed = true;                                        
  56.  56.         }                                                           
  57.  57.                                                                     
  58.  58.         return resultCode;                                          
  59.  59.     }                                                               
  60.  60.     finally {                                                       
  61.  61.         UtilTimerStack.pop(profileKey);                             
  62.  62.     }                                                               
  63.  63. }     
  64.  64.     
  65.  65//invokeAction    
  66.  66protected String invokeAction(Object action,ActionConfig actionConfig)throws Exception{    
  67.  67.     String methodName = proxy.getMethod();    
  68.  68.     
  69.  69.     String timerKey = "invokeAction: " + proxy.getActionName();    
  70.  70.     try {    
  71.  71.         UtilTimerStack.push(timerKey);    
  72.  72.     
  73.  73.         boolean methodCalled = false;    
  74.  74.         Object methodResult = null;    
  75.  75.         Method method = null;    
  76.  76.         try {    
  77.  77.             //java反射机制得到要执行的方法    
  78.  78.             method = getAction().getClass().getMethod(methodName, new Class[0]);    
  79.  79.         } catch (NoSuchMethodException e) {    
  80.  80.             // hmm -- OK, try doXxx instead    
  81.  81.             //如果没有对应的方法,则使用do+Xxxx来再次获得方法       
  82.  82.             try {    
  83.  83.                 String altMethodName = "do" + methodName.substring(01).toUpperCase() + methodName.substring(1);    
  84.  84.                 method = getAction().getClass().getMethod(altMethodName, new Class[0]);    
  85.  85.             } catch (NoSuchMethodException e1) {    
  86.  86.                 // well, give the unknown handler a shot    
  87.  87.                 if (unknownHandlerManager.hasUnknownHandlers()) {    
  88.  88.                     try {    
  89.  89.                         methodResult = unknownHandlerManager.handleUnknownMethod(action, methodName);    
  90.  90.                         methodCalled = true;    
  91.  91.                     } catch (NoSuchMethodException e2) {    
  92.  92.                         // throw the original one    
  93.  93.                         throw e;    
  94.  94.                     }    
  95.  95.                 } else {    
  96.  96.                     throw e;    
  97.  97.                 }    
  98.  98.             }    
  99.  99.         }    
  100. 100.         //执行Method    
  101. 101.         if (!methodCalled) {    
  102. 102.             methodResult = method.invoke(action, new Object[0]);    
  103. 103.         }    
  104. 104.         //从这里可以看出可以Action的方法可以返回String去匹配Result,也可以直接返回Result类    
  105. 105.         if (methodResult instanceof Result) {    
  106. 106.             this.explicitResult = (Result) methodResult;    
  107. 107.     
  108. 108.             // Wire the result automatically    
  109. 109.             container.inject(explicitResult);    
  110. 110.             return null;    
  111. 111.         } else {    
  112. 112.             return (String) methodResult;    
  113. 113.         }    
  114. 114.     } catch (NoSuchMethodException e) {    
  115. 115.         throw new IllegalArgumentException("The " + methodName + "() is not defined in action " + getAction().getClass() + "");    
  116. 116.     } catch (InvocationTargetException e) {    
  117. 117.         // We try to return the source exception.    
  118. 118.         Throwable t = e.getTargetException();    
  119. 119.     
  120. 120.         if (actionEventListener != null) {    
  121. 121.             String result = actionEventListener.handleException(t, getStack());    
  122. 122.             if (result != null) {    
  123. 123.                 return result;    
  124. 124.             }    
  125. 125.         }    
  126. 126.         if (t instanceof Exception) {    
  127. 127.             throw (Exception) t;    
  128. 128.         } else {    
  129. 129.             throw e;    
  130. 130.         }    
  131. 131.     } finally {    
  132. 132.         UtilTimerStack.pop(timerKey);    
  133. 133.     }    
  134. 134. }    


 

action执行完了,还要根据ResultConfig返回到view,也就是在invoke方法中调用executeResult方法。

  1.  1private void executeResult() throws Exception {    
  2.  2.     //根据ResultConfig创建Result     
  3.  3.     result = createResult();    
  4.  4.     
  5.  5.     String timerKey = "executeResult: " + getResultCode();    
  6.  6.     try {    
  7.  7.         UtilTimerStack.push(timerKey);    
  8.  8.         if (result != null) {    
  9.  9.         //开始执行Result,    
  10. 10.         //可以参考Result的实现,如用了比较多的ServletDispatcherResult,ServletActionRedirectResult,ServletRedirectResult     
  11. 11.             result.execute(this);    
  12. 12.         } else if (resultCode != null && !Action.NONE.equals(resultCode)) {    
  13. 13.             throw new ConfigurationException("No result defined for action " + getAction().getClass().getName()    
  14. 14.                     + " and result " + getResultCode(), proxy.getConfig());    
  15. 15.         } else {    
  16. 16.             if (LOG.isDebugEnabled()) {    
  17. 17.                 LOG.debug("No result returned for action " + getAction().getClass().getName() + " at " + proxy.getConfig().getLocation());    
  18. 18.             }    
  19. 19.         }    
  20. 20.     } finally {    
  21. 21.         UtilTimerStack.pop(timerKey);    
  22. 22.     }    
  23. 23. }              
  24. 24.     
  25. 25public Result createResult() throws Exception {    
  26. 26.     //如果Action中直接返回的Result类型,在invokeAction()保存在explicitResult    
  27. 27.     if (explicitResult != null) {                               
  28. 28.         Result ret = explicitResult;                            
  29. 29.         explicitResult = null;                                  
  30. 30.                                                                 
  31. 31.         return ret;                                             
  32. 32.     }    
  33. 33.     //返回的是String则从config中得到当前Action的Results列表    
  34. 34.     ActionConfig config = proxy.getConfig();                    
  35. 35.     Map<String, ResultConfig> results = config.getResults();    
  36. 36.                                                                 
  37. 37.     ResultConfig resultConfig = null;                           
  38. 38.                                                                 
  39. 39.     synchronized (config) {                                     
  40. 40.         try {     
  41. 41.             //通过返回的String来匹配resultConfig      
  42. 42.             resultConfig = results.get(resultCode);             
  43. 43.         } catch (NullPointerException e) {                      
  44. 44.             // swallow                                          
  45. 45.         }                                                       
  46. 46.         if (resultConfig == null) {                             
  47. 47.             // If no result is found for the given resultCode, try to get a wildcard '*' match.    
  48. 48.             //如果找不到对应name的ResultConfig,则使用name为*的Result      
  49. 49.             //说明可以用*通配所有的Result                                  
  50. 50.             resultConfig = results.get("*");    
  51. 51.         }                                       
  52. 52.     }                                           
  53. 53.                                                 
  54. 54.     if (resultConfig != null) {                 
  55. 55.         try {    
  56. 56.             //创建Result     
  57. 57.             return objectFactory.buildResult(resultConfig, invocationContext.getContextMap());    
  58. 58.         } catch (Exception e) {    
  59. 59.             LOG.error("There was an exception while instantiating the result of type " + resultConfig.getClassName(), e);    
  60. 60.             throw new XWorkException(e, resultConfig);    
  61. 61.         }     
  62. 62.     } else if (resultCode != null && !Action.NONE.equals(resultCode) && unknownHandlerManager.hasUnknownHandlers()) {    
  63. 63.         return unknownHandlerManager.handleUnknownResult(invocationContext, proxy.getActionName(), proxy.getConfig(), resultCode);    
  64. 64.     }               
  65. 65.     return null;    
  66. 66. }       
  67. 67.     
  68. 68public Result buildResult(ResultConfig resultConfig, Map<String, Object> extraContext) throws Exception {    
  69. 69.     String resultClassName = resultConfig.getClassName();    
  70. 70.     Result result = null;                                    
  71. 71.                                                              
  72. 72.     if (resultClassName != null) {    
  73. 73.         //buildBean中会用反射机制Class.newInstance来创建bean     
  74. 74.         result = (Result) buildBean(resultClassName, extraContext);    
  75. 75.         Map<String, String> params = resultConfig.getParams();         
  76. 76.         if (params != null) {                                          
  77. 77.             for (Map.Entry<String, String> paramEntry : params.entrySet()) {    
  78. 78.                 try {    
  79. 79.                      //reflectionProvider参见OgnlReflectionProvider;    
  80. 80.               //resultConfig.getParams()就是result配置文件里所配置的参数<param></param>     
  81. 81.                      //setProperties方法最终调用的是Ognl类的setValue方法       
  82. 82.               //这句其实就是把param名值设置到根对象result上    
  83. 83.                     reflectionProvider.setProperty(paramEntry.getKey(), paramEntry.getValue(), result, extraContext, true);    
  84. 84.                 } catch (ReflectionException ex) {     
  85. 85.                     if (LOG.isErrorEnabled())          
  86. 86.                         LOG.error("Unable to set parameter [#0] in result of type [#1]", ex,    
  87. 87.                                 paramEntry.getKey(), resultConfig.getClassName());    
  88. 88.                     if (result instanceof ReflectionExceptionHandler) {               
  89. 89.                         ((ReflectionExceptionHandler) result).handle(ex);             
  90. 90.                     }    
  91. 91.                 }        
  92. 92.             }            
  93. 93.         }                
  94. 94.     }                    
  95. 95.                          
  96. 96.     return result;       
  97. 97. }     


 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值