SAStrutsを読む:Struts以降
さっきのつづき。
デバッガでIndexAction#index()にブレークポイント張ってS2RequestProcessor#processからのスタックトレースを見てみる。
(インターセプタの処理略) satest.action.IndexAction$$EnhancedByS2AOP$$9ac272.index() (Method.invoke関係略) org.seasar.framework.util.MethodUtil.invoke(java.lang.reflect.Method, java.lang.Object, java.lang.Object[]) org.seasar.struts.action.ActionWrapper.execute(javax.servlet.http.HttpServletRequest, org.seasar.struts.config.S2ExecuteConfig) org.seasar.struts.action.ActionWrapper.execute(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) org.seasar.struts.action.S2RequestProcessor(org.apache.struts.action.RequestProcessor) org.seasar.struts.action.S2RequestProcessor.process(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
ActionWrapperがディスパッチ本体と見た。
RequestProcessorがActionWrapperのインスタンス見つけて呼ぶ部分はわからないがとりあえずActionWrapperを読んでみる
//ActionWrapper#execute @Override public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { S2ExecuteConfig executeConfig = S2ExecuteConfigUtil.getExecuteConfig(); if (executeConfig != null) { return execute(request, executeConfig); } return null; }
S2ExecuteConfigにはディスパッチ対象となるアクションのメソッドとか入ってる。なぜスタティックメソッドなのかというと、内部ではSingletonS2Container.getComponent使ってHttpServletRequestを取得してるから。
public static S2ExecuteConfig getExecuteConfig() { return (S2ExecuteConfig) RequestUtil.getRequest().getAttribute(S2ExecuteConfigUtil.class.getName()); } public static HttpServletRequest getRequest() { return SingletonS2Container.getComponent(HttpServletRequest.class); }
S2ExecuteConfig取得後実行されるアクション起動のコードはこれ。
protected ActionForward execute(HttpServletRequest request, S2ExecuteConfig executeConfig) { ActionMessages errors = new ActionMessages(); List<S2ValidationConfig> validationConfigs = executeConfig .getValidationConfigs(); if (validationConfigs != null) { // バリデーション起動部省略 // まあバリデータ呼んでるだけだと思います } if (!errors.isEmpty()) { return processErrors(errors, request, executeConfig); } // バリデーション成功したらアクションを呼ぶ // ちなみにactionはActionMapping#getAction()で取得 // nextはアクションの帰り値、すなわち遷移先jspのパス String next = (String) MethodUtil.invoke(executeConfig.getMethod(), action, null); // 必要があればアクションフォーム除去 if (executeConfig.isRemoveActionForm()) { RequestUtil.getRequest().getSession().removeAttribute( actionMapping.getActionFormComponentDef() .getComponentName()); RequestUtil.getRequest().removeAttribute( actionMapping.getAttribute()); } // リダイレクトの設定 boolean redirect = executeConfig.isRedirect(); if (redirect && ActionMessagesUtil.hasErrors(request)) { redirect = false; } // そしてActionForwardを返す return actionMapping.createForward(next, redirect); }
まあそんなもんですね。
Actionクラスのアノテーションは誰かが解析してexecuteConfigに設定済み。どこでやってんだこれ。DIコンテナ方面か。
まとめ
ソースの流れ追って、デバッガでステップ実行したけどこれくらいしかわからなかった。
S2ExecuteConfig作ってるのはActionCustomizerらしい。このへんの流れはS2Containerの知識が必要。
DIコンテナがあると処理の流れが非常に追いにくくて困る。規約知ってればわかりやすいんでしょうけどね。