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包加载类


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