EasyJF 官方网站全面升级,同时EasyJF开源团队也将进行全面改组,期待您给我们提出宝贵的意见及建议!

当前位置:首页-技术前沿-应用框架-Spring

  • Guice开发实战(一)
    作者: 本站会员  来源:easyjf  发布时间:2007-10-14 17:28:00
  • 公元二零零七年,开源领域各IoC框架战火不断。Spring大红大紫,独领风骚;PicoContainer、Hivemind紧随其后,穷追不舍。正当各路豪杰稳步发展之时,一匹黑马悄悄杀进江湖,这就是号称比Spring快100倍的Guice,从此江湖又起风云!

           Guice是由Bob lee设计的基于Java5 Annotation的轻量级IoC容器,它把组织对象依赖关系的逻辑从XML文件转移到对象内部,巧妙的实现了DI模式。本文并不打算详细讲解Guice的语法,如果你尚且不知道Guice是什么,可以先阅读附录中提供的文章了解Guice相关信息。本文余下部分将用一个以Guice为基础的简单的MVC模式的参考实现(实在是不知道应该叫什么,暂且就称之为参考实现吧)以及在该实现基础上开发的XXX示例来深入Guice应用开发实战。
     
    声明:
    本文所述之 AromaRI,MVC Pattern Reference Implementation 完全出于演示目的,请勿以名称及设计之好坏进行任何恶意评论,在此深表谢意! 
     

     

    接下来让我们一起开始愉快的Guice之旅!!
     
    友情提醒:
    编写本文之目的在于通过项目实战讲解Guice及其相关技术,让读者能够迅速获得Guice开发经验,并能够应用于实际项目之中。所以,请明确你是在学习Guice而非笔者设计的AromaRI!
    AromaRI实现原理:

     

     


           AromaRI,其名字本身并没有特殊内涵,笔者在设计时为取一个合适的名字而伤透脑筋。很多人喜欢把自己设计的东西称为“框架”、“Framework”,另一些人认为其原理或实现过于简单并不能称之为Framework,因而导致双方激烈的口舌之战。为避免不必要的争论,笔者没有采用XXX Framework的名字,而是起了一个简单的名字——AromaRI。尽管RI(Reference Implementation)也不恰当,但请读者勿以该名字为由进行任何评论!
     
          或许此时此刻你会有这样的疑问:JAVA领域开源的MVC框架多如牛毛,你为什么还要自己写一个实现呢?就笔者的经验来看,任何一种MVC框架,无论是基于请求-响应模式还是基于事件驱动模式,或高或低都有一定的学习难度。编写本文之目的在于通过项目实战来讲解Guice及其相关技术,让读者能够迅速获得Guice开发经验并可以在自己的项目中应用Guice。因此,为了避免读者将时间花费在学习某种MVC框架上,笔者设计了现在的AromaRI。AromaRI是一个基于“请求-响应”方式的MVC参考实现(MVC Pattern Reference Implementation)。它非常简单,只由为数不多的几个类构成,实现了MVC模式的基本功能,足够演示之用,而且读者掌握它几乎没有任何难度!
     
          说了这么多废话,该是进入正题的时候了。AromaRI由一个Servlet、一个Container和若干Action构成。该Servlet应用了经典的J2EE前端控制器模式,实现了模型和视图相分离。下面让我们来看一下AromaRI的工作原理示例图:
    上图比较清晰地描述了AromaRI的工作原理,但略显复杂。因此,笔者特意将上图拆分成两
    部分进行讲解,如下:
     
     
     如上图所示,AromaServlet作为应用唯一入口,统一接收用户请求并根据规则指派Action类处理用户请求。ActionContext用于在AromaServlet和Action之间传递数据,封装了HttpServletRequest参数。Container作为Action容器,为当前请求提供Action实例。
    注意:从Container中获取的Action实例已经按照Guice的规则自动进行依赖注入。
     
     
     
    该图演示了Container Architecture的工作方式:SingletonContainerLoader调用ConfigParser解析应用配置文件-aromari-components.xml,并根据解析结果(此处是Component数组)构造DefaultContainer实例,最后调用容器的init方法进行容器初始化。执行完毕,将该容器放入当前线程上下文中,以共其他地方引用。
    注意:这里忽略了一个细节 - 容器初始化过程中可以注册用户自定义的Module,后面会有详细讲解。
     

           相信看到此处,稍有经验的读者都已经非常清楚AromaServlet和Action的原理和工作方式了。惟独这个Container会让大家心存疑惑:


    • Container如何初始化?
      Container和Guice之间是什么关系?
      如何从Container获取Action对象?
      Container中的Action如何实现自动注入依赖对象?
      Container中的Action有没有作用域?
      Container中的Action如何工作?
      能否通过Container查找非Action对象?


            或许思维敏捷的你还有更多的疑问,那么就请跟随笔者的思路一步步解开心中的疑惑。

           在解答这些问题之前还是需要介绍一下AromaRI中Action的工作原理。Action接口参考了国产开源框架EasyJWeb中Action的设计原理,但做了大量的简化,因此功能上也削弱了大半。但作为演示之用,足以满足我们的需求。如果读者希望进行更加深入的研究,请到EasyJWeb官方网站了解更多信息。Action接口中只有一个方法:public void execute(ActionContext context); ActionContext作为请求上下文封装了HttpServletRequest和HttpServletContext,实现与WEB层的分离。所有Http请求中的参数都会自动被填加到ActionContext中并传递给Action对象,在ActionContext中可以通过如下方法获取Http请求中的参数:public Object getParameter(String name); Action在处理完该请求之后可以调用public void addResult(String name, Object value); 方法将结果设置到Http请求的属性当中,页面上可以直接引用这些结果对象。在ActionContext中还有一个方法用于设置响应页面public void setNextPage(String page); 仅此而已,剩下的工作就由AromaServlet自动完成。在WEB应用开发中经常会遇到这种情况:一个Action通常要处理多个操作,如对用户信息的增、删、改、查通常都会放到一个Action中以减少类的数量,降低维护成本。一个可选的办法就是在请求中设置一个参数代表当前的操作,然后在execute()方法中做N多的IF/ELSE判断来决定到底应该调用哪个操作,这也是很多人的正在采用的做法。AromaRI默认提供了一个Action支持类:ActionSupport,可以幽雅地解决这个问题。任何继承ActionSupport的类都可以定义若干个处理方法,然后在请求中增加一个参数“command=xxx”来决定具体调用哪个方法,没有任何IF/ELSE判断。但是这里有一个约定,所有方法都必须遵循如下的语法规则:public void doXxxXxxx(ActionContext context) {} 相信这个约定不用我来解释,你一定已经非常熟悉它了!例如你的Action类中有这样一个修改用户信息的方法:

    public void doEditUser(ActionContext context) {
      String id = (String)context.getParameter("id");
      String name = (String)context.getParameter("name");
            userService.editUser(id,name);
    }
    那么如果你在request中增加一个参数“command=editUser”,该方法就会被执行,注意参数的大小写!


    友情提醒:
    在AromaRI中并没有FormBean的概念,也就是说请求中的参数并不会被自动组装成FormBean供你使用!ActionContext充当了参数传递的载体,但它并不是一个FormBean,当你需要取得某个参数的值时可以调用ActionContext的getParameter方法,AromaRI也不会对你的参数进行效验! 

           如果你也和我一样喜欢偷懒,那么你下面介绍的特性一定会让你很兴奋(如果你非常熟悉Webwork,那么也请看看如何通过注解来进行变量的自动注入)!在AromaRI中,你可以把要接收的参数定义成Action类的属性,然后为这些属性增加set和get方法,AromaRI会自动根据ActionContext中的值为这些属性设值。类似这样:

    private String id;
     private String name;
     
     public String getId() {
      return id;
     }
     public void setId(String id) {
      this.id = id;
     }
     public String getName() {
      return name;
     }
     public void setName(String name) {
      this.name = name;
     }
    public void doEditUser(ActionContext context) {
            userService.editUser(id,name );
    }
      如果你连set和get方法都懒得写,那么你也可以使用AromaRI提供的@Autowire注解来标记要进行自动设值的属性,无论是私有类型还是保护类型(不建议使用Public类型)!类似下面的用法:
    @Autowire private String id;
     @Autowire private String name;
    public void doEditUser(ActionContext context) {
            userService.editUser(id,name );
    }
    AromaRI会根据自动为带有@Autowire注解的属性设值。所有这些是如何实现的呢?答案就在ActionEnhancer类。这是一个Action的增强类,可以在Action执行之前对Action做一些处理,例如属性的自动注入。ActionEnhancer类只有一个静态方法:
    static Action enhance(Action action, ActionContext context) {
    
      if (AromaUtil.isEmptyOrNull(action) || AromaUtil.isEmptyOrNull(context)) {
       if (logger.isDebugEnabled()) {
        logger.debug("Action or ActionContext may be null , so ignore it!");
       }
       return action;
      }
    
      autowireActionProperties(action, context);
    
      return action;
     }
    该方法用于对Action类进行处理,其中下划线加粗的方法(限于篇幅,方法内容请查看源代码)用于进行属性的自动设值。显而易见,可以很容易的在该方法中对Action类进行方法拦截等其他操作。ActionEnhancer类并不用开发人员来手工调用,AromaServlet根据请求从Guice中取得Action实例后会自动调用ActionEnhancer对该Action进行处理。尽管如此,充满好奇心和求知欲的你也一定迫不及待的想知道具体的调用方式,下面的代码片段或许会对你有所帮助,更加详细的信息请参看AromaServlet类的doGet方法。
    beforeProcess(req, res, context);
    
    Action action = ActionEnhancer.enhance((Action) container.getBean(getActionName(req, res)), context);
    if (AromaUtil.isEmptyOrNull(action)) {
     handleError(req, res, "The action that you just request dose not exist!");
    }
    action.execute(context);
    
    afterProcess(req, res, context);
    对Action的讲解就到此为止,后面还会有一些简单的例子来演示具体用法。接下来该让我们揭开Container的神秘面纱了!


    Container初始化流程及工作原理:


           在AromaRI中,所有的Action和业务层组件,包括数据访问组件都是通过Guice进行管理,并实现依赖对象的自动注入。Container是AromaRI和Guice的结合点,对Guice进行了适当的封装。

    待续。。。

     

     


    本文组织结构

     


    AromaRI实现原理


           AromaRI是一个基于“请求-响应”方式的MVC参考实现(MVC Pattern Reference Implementation),它非常的简单,只由为数不多的几个类构成。该部分简要介绍AromaRI的实现原理,并演示其使用方法。

    XXX案例研究

           案例是最能说明问题的表达方式,此处通过XXX案例详细讲解如何在AromaRI中使用Guice,在其他框架中也可以通过类似的方式集成Guice。你将发现,事情原来如此简单!

    Guice源码分析
     
           掌握一种开源框架并能够理解其设计思想,其终极之道莫过于阅读框架源码了。该部分将带领读者一起深入Guice框架内部,研究其实现原理,领会其设计思想。
     
    EasyJWeb与Guice集成
           EasyJWeb是一个国产的简易JAVA WEB开发框架,它简单、易用,可以很容易的和其他IoC框架进行集成。本部分详细讲解如何在EasyJWeb项目中使用Guice。
     
    总结
           说明
     
    附录
     
           附录中介绍了一些关于Guice框架的有用资源,读者可以通过阅读这些资源了解更多Guice相关知识。
     
     
     

  • 评论 】 【收藏】 【 推荐给朋友 】 【字体: 】 【关闭
评论:共0条

发表评论:
评论: 
    

相关栏目

  • 如何才能得到国外最新的技术

Copyright (C) 2005 EasyJF.com 简易java框架网 渝ICP备06004507号
如有意见请与我们联系