`

Guice开发实战

阅读更多

本文转载地址:http://www.easyjf.com/html/20071014/851984.html

     

     公元二零零七年,开源领域各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相关知识。

 

 

  • 大小: 76.7 KB
  • 大小: 20.4 KB
  • 大小: 34 KB
分享到:
评论

相关推荐

    JAVA WEB典型模块与项目实战大全

    《Java Web典型模块与项目实战大全(程序员典藏)》以实战开发为原则,以Java EE主流框架整合应用及项目开发为主线,通过Java Web开发中最常见的19个典型模块和5个完整的项目案例,详细介绍了Struts 2.x、Spring、...

    JAVA WEB典型模块与项目实战大全.zip

    《Java Web典型模块与项目实战大全》以实战开发为原则,以Java EE主流框架整合应用及项目开发为主线,通过Java Web开发中最常见的19个典型模块和5个完整的项目案例,详细介绍了Struts 2.x、Spring、Guice、Hibernate...

    Java.Web典型模块与项目实战大全

    《Java Web典型模块与项目实战大全(程序员典藏)》以实战开发为原则,以Java EE主流框架整合应用及项目开发为主线,通过Java Web开发中最常见的19个典型模块和5个完整的项目案例,详细介绍了Struts 2.x、Spring、...

    JAVA WEB典型模块与项目实战大全.part2(第二卷)

    第22章 用户登录模块(Struts 2.X+Guice+国际化) 第3篇 项目案例实战 第23章 在线音乐管理系统(AJAX+JSP+Struts 2.X) 第24章 数据汇聚系统(Struts 2.X+Spring+iBATIS) 第25章 投票管理系统(Struts 2.X+Spring+...

    java实战开发1200例源码-webpieces:一个包含所有Web部分(WITHapis)的项目,用于创建一个Web服务器(和一个实际的W

    java实战开发1200例源码网片 Codecov.io / jacoco 有两个bug,一个与聚合报告有关(所以我们实际上高于这个数字) 很难缩小我最喜欢的 5 个功能的范围,但可以尝试一下 你可以在不分叉 git repo 的情况下修复 ...

    JAVA WEB典型模块与项目实战大全.part4

    第22章 用户登录模块(Struts 2.X+Guice+国际化) 第3篇 项目案例实战 第23章 在线音乐管理系统(AJAX+JSP+Struts 2.X) 第24章 数据汇聚系统(Struts 2.X+Spring+iBATIS) 第25章 投票管理系统(Struts 2.X+Spring+...

    JAVA WEB典型模块与项目实战大全.part3(第三卷)

    第22章 用户登录模块(Struts 2.X+Guice+国际化) 第3篇 项目案例实战 第23章 在线音乐管理系统(AJAX+JSP+Struts 2.X) 第24章 数据汇聚系统(Struts 2.X+Spring+iBATIS) 第25章 投票管理系统(Struts 2.X+Spring+...

    JAVA WEB典型模块与项目实战大全.part1(第一卷)

    第22章 用户登录模块(Struts 2.X+Guice+国际化) 第3篇 项目案例实战 第23章 在线音乐管理系统(AJAX+JSP+Struts 2.X) 第24章 数据汇聚系统(Struts 2.X+Spring+iBATIS) 第25章 投票管理系统(Struts 2.X+Spring+...

Global site tag (gtag.js) - Google Analytics