Guice开发实战
本文转载地址:http://www.easyjf.com/html/20071014/851984.html
公元二零零七年,开源领域各IoC框架战火不断。Spring大红大紫,独领风骚;PicoContainer、Hivemind紧随其后,穷追不舍。正当各路豪杰稳步发展之时,一匹黑马悄悄杀进江湖,这就是号称比Spring快100倍的Guice,从此江湖又起风云!
声明:
本文所述之 AromaRI,MVC Pattern Reference Implementation 完全出于演示目的,请勿以名称及设计之好坏进行任何恶意评论,在此深表谢意!
友情提醒:
编写本文之目的在于通过项目实战讲解Guice及其相关技术,让读者能够迅速获得Guice开发经验,并能够应用于实际项目之中。所以,请明确你是在学习Guice而非笔者设计的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的工作原理示例图:
注意:从Container中获取的Action实例已经按照Guice的规则自动进行依赖注入。
注意:这里忽略了一个细节 - 容器初始化过程中可以注册用户自定义的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); }
友情提醒:
在AromaRI中并没有FormBean的概念,也就是说请求中的参数并不会被自动组装成FormBean供你使用!ActionContext充当了参数传递的载体,但它并不是一个FormBean,当你需要取得某个参数的值时可以调用ActionContext的getParameter方法,AromaRI也不会对你的参数进行效验!
如果你也和我一样喜欢偷懒,那么你下面介绍的特性一定会让你很兴奋(如果你非常熟悉Webwork,那么也请看看如何通过注解来进行变量的自动注入)!在AromaRI中,你可以把要接收的参数定义成Action类的属性,然后为这些属性增加set和get方法,AromaRI会自动根据ActionContext中的值为这些属性设值。类似这样:
Container初始化流程及工作原理:
在AromaRI中,所有的Action和业务层组件,包括数据访问组件都是通过Guice进行管理,并实现依赖对象的自动注入。Container是AromaRI和Guice的结合点,对Guice进行了适当的封装。
待续。。。
本文组织结构
AromaRI实现原理
AromaRI是一个基于“请求-响应”方式的MVC参考实现(MVC Pattern Reference Implementation),它非常的简单,只由为数不多的几个类构成。该部分简要介绍AromaRI的实现原理,并演示其使用方法。
XXX案例研究
案例是最能说明问题的表达方式,此处通过XXX案例详细讲解如何在AromaRI中使用Guice,在其他框架中也可以通过类似的方式集成Guice。你将发现,事情原来如此简单!
Guice源码分析