jrouter源碼分析

最近由於工作原因研究了jrouter,簡單的記錄和分享下。

一,項目介紹

jrouter是一套基於配置和annotation攔截方法的框架,專注方法的映射、調用、攔截和結果處理,比較強大。項目地址http://code.google.com/p/jrouter/

二,實現思路

首先說標籤,jrouter提供了Action,Interceptor,result,namespace等標籤,通過spring文件將自定義的"標籤實現類"加載到內存中。標籤是一種對真正執行代理的映射,在感興趣的method上定義想要的標籤和name。兩層代理,一層是對標籤的代理(ActionProxy或InterceptorProxy),action和interceptor的代理,由ActionFactory產生;往下一層是具體的proxy(使用javassitproxy產生的代理對象),由ProxyFactory產生。總體來看,jrouter是標籤和代理的結合運用。


三,關鍵路徑分析

入口類DefaultActionFactoryBean(又是FactoryBean)會在屬性初始化後將“代理環境”搭建起來,其中有個屬性classScannerProperties定義了掃描類的規則,在buildActionFactory過程中將所有符合規則的類加載,jrouter就是給這些類加上一層代理,所以同時一起初始化的還有Action,interceptor等自定義實現。整個初始化過程就是對jrouter-spring的解析+設置代理的過程。

測試執行過程:

factory = new DefaultActionFactory();

        //interceptor
        factory.addInterceptors(SampleInterceptor.class);

        //interceptor stack
        factory.addInterceptorStacks(DefaultInterceptorStack.class);

        //result
        factory.addResultTypes(DefaultResult.class);

        //aciotn
        //class
        factory.addActions(jrouter.URLTestAction.class);
        //object

        factory.addActions(new jrouter.URLTestAction2());

factory.invokeAction("");

invokeAction過程中根據參數創建調用上下文,ActionInvocation invocation = createActionInvocation(path, params);

那麼後面自然是對action和interceptor的調用了,這裏用到了recursive invoke。直接上代碼:

//recursive invoke
        if (interceptors != null && _index < interceptors.size()) {
            final InterceptorProxy interceptor = interceptors.get(_index++);
            LOG.debug("Invoke Interceptor [{}] at : {}", interceptor.getName(), interceptor.getMethod());
            invokeResult = interceptor.isRequireAction() ? interceptor.invoke(this) : interceptor.invoke();
        } else {
            //action invoke
            if (!executed) {
                invokeActionOnly(params);
            }
        }
        return invokeResult;


再往後使用Java反射或代理對象調用底層方法:

使用Java反射或代理對象調用底層方法:

return proxy == null ? method.invoke(obj, params) : proxy.invoke(method, obj, params);

**************分割線*************

看下創建Action代理類(ActiionProxy)時取得這個Action的攔截代理的實現:

Action action = method.getAnnotation(Action.class);
//action中申明的interceptors
            for (String name : action.interceptors()) {
                InterceptorProxy ip = interceptors.get(name);
                if (ip == null) {
                    LOG.warn("No such Interceptor [{}] at : {}", name, ap.getMethod());
                } else {
                    inters.add(ip);
                }
            }




可以是根據標籤配置的攔截器的name從內存的攔截器集合中取到的。真正執行invoke時只要像上述遍歷所有攔截器即可。

四,總結

這種基於標籤和配置的方式擴展性很強,適合於短小精幹的批量的攔截場景,同時學習成本也比較大,跟我想要的攔截模型還不太一樣,但也是有參考價值的。javaassist和reflectasm同樣操作字節碼但使用上方式有很大差別,後面有時間寫篇兩者對比的文章。

最新的文章和分享都放在個人博客:www.b2notes.com ,歡迎訪問。

使用asm分析jar包加載類


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章