几乎所有的开源框架都有配置。配置之所以能够作为一个很重要的内容成为开源框架的一部分,可能基于以下的原因:
1. 配置是避免硬编码的有效途径
通过配置,我们可以非常轻松的替换某些运行参数、替换接口的实现类等,从而达到使程序更加灵活的目的。在这里,最典型的例子就是基于XML的Spring的配置文件。由于Spring提倡的面向接口的编程,使得你可以通过配置来灵活地替换内部实现,从而可以轻而易举地改变程序的运行特性。
2. 配置必须被用于指定某些映射关系
这一点其实大家也深有体会。以Hibernate为例,ORM的映射关系最早就是通过XML配置文件来指定的。而许多传统的Web层框架,更加通过XML配置文件,来指定URL与Control层的Java类的映射关系。
3. 配置能提供系统运行必须的参数
这一点与第一点非常类似,只是目的迥异。第一点的目的在于偷懒,在于保持足够的灵活性。而这里,我们可能不得不将一些系统化的参数进行固化处理,从而用到了配置文件。
有关配置的讨论
基于上面所提到的三点的原因,配置文件被认为是架起外界与程序之间的桥梁、是反应框架内部功能的一面镜子、更是程序是否灵活的一个重要标准,同时,其也成为了程序员学习框架时必须迈过的一道坎。说它是一道坎,一点也不过分,因为随着时代的发展,程序员们已经越来越开始报怨配置文件的庞大和无序,报怨过多的重复的配置劳动力成本,报怨配置本身的学习成本。
于是,一场试图改变当前生活状态的大讨论轰轰烈烈的开始。我从Javaeye上摘录了几篇有价值的讨论,分别站在不同的角度,对配置这一问题进行了剖析:
1. 从配置文件的归类和使用方式上入手
[downpour] 若干条J2EE应用中运用“配置”的最佳实践:http://www.iteye.com/topic/185542
2. 有关配置的表现形式的讨论
[ahuaxuan] xml和annotation的是是非非:http://www.iteye.com/topic/178725
[Readonly] 如何才算滥用annotation?:http://www.iteye.com/topic/16062
3. 试图通过改进框架,来加强或简化配置
[cnoss] 让你的 Ibatis2 也支持Annotation:http://www.iteye.com/topic/251047
[downpour] LightURL——打造零配置的Struts2开发方式:http://www.iteye.com/topic/242838
配置的现状和趋势
随着时代的发展,人们对配置的要求越来越高,这些高要求体现在:不丧失程序的灵活性,但是要保持尽量简单。于是,有关配置的现状和趋势,就体现为:表现形式的多样化和命名约定的广泛使用性。
表现形式的多样性,就要求我们能够根据实际情况在配置的不同表现形式中做出选择。在ahuaxuan的《xml和annotation的是是非非》中,讨论了如何在xml和annotation中做出合理的选择:
于是我们看到我的项目里到处都是xml配置文件,从struts,到 hibernate,而且尤其是struts和hibernate,一个中型项目,struts的xml配置文件有时候达到数万行,再大一点的,可以数十万行,虽然很多时候都是拷贝,粘贴,但是看这个这个数十个几千行的struts配置文件能不让人倒胃口吗。再说那个hbm.xml,大家再熟悉不过了,你想想吧,一个几域模型的项目里,你需要有多少配置文件,我眼睛都看花了。这些都是xml的缺点。
Model一个field上挂了O/R Mapping, Full Text Index, Validation, Security...如果这么多配置不放在annotation中还是需要放在配置文件中,那么一个model就需要很多配置文件了
偶的意见就是要分开多个配置文件,减少Line Of Code per File,减少维护成本,降低出错概率,分离关注点。
而在这里,我也再次重申一下我的观点:
某个Annotation受到欢迎的程度我觉得取决于两点,一个是Annotation是否足够简单,例如像Spring2.5中的@Service,@Autowired。另外一个,就是如果有相应的XML配置,是否能完成“弱智”过度。我这里所说的弱智过度其实就是指Annotation中的语义是否能够和XML中的属性语义保持一致,以至于那些原本从XML过度到Annotation的朋友可以很容易的就切换过来。这一点,Struts2的Annotation就做得比较好,但是Hibernate的Annotation就很不容易让人产生联想。
事实上,我个人很反对在一个Domain Model上加Annotation来完成类似持久化、搜索等语义。就像Readonly说的,一个Domain Model就是一个Domain Model,很多情况下,我需要在其中填充一些业务逻辑,或者甚至我只想看看有那些字段。加上了过多的Annotation,导致这个文件臃肿不堪,也搞不清楚它到底承担了多少责任。甚至还要因为某些Annotation增加很多不必要的工作量。比如,没事情在Domain Model里面加了一个额外的getter方法为了前台显示用,结果为了Hibernate还要搞个恶心的@Transit的annotaion。实在是不能让人接受。。
当然,这是一个仁者见仁智者见智的问题,希望大家可以从讨论中多多思考,获取自己的观点。
至于说到命名约定,RoR已经在这个方面为我们做出了强烈的表率作用。而从Spring开始提倡使用@Autowired的Annotation,到Struts2的零配置插件的不断涌现,也正体现了配置正在越来越往这个方向靠。大家也可以在学习的过程中,多多注意命名约定在项目中的使用,从中学到几招最佳实践。
Struts2中的配置
Struts2作为一个传统的MVC框架,同样有很多基础配置。包括它的前身Webwork2在内,最早也是完全使用XML作为全程的配置语义的。
从配置文件的管理和配置结构上来讲,Struts2优于之前的许多Web层框架。这一点moxie曾经写过一篇文章介绍过:
[moxie] WebWork2多模块解决方法:http://www.iteye.com/topic/6529
从XML的语义设计来看,Struts2和Webwork2比起他们的先辈来说,也有明显的进步,不会在出现Struts1中,name居然表示actionForm这样让人匪夷所思的语义了。
从功能上来说,Struts2的配置文件不仅提供了URL到Control层的映射关系的定义,同时也成为了一个简单的容器定义的场所。所以,事实上Struts2包含了双重的功能。有关容器和IoC方面的内容,我在后面的章节会详细介绍。
而Struts2在配置简化方面,由于它提供了插件的机制,所以这部分功能往往由插件来完成。有兴趣的读者可以自行参考相关的插件:
codebehind:http://cwiki.apache.org/S2PLUGINS/codebehind-plugin.html
smarturls:[url]http://cwiki.apache.org/S2PLUGINS/smarturls-plugin.html [/url]
lighturl:http://www.iteye.com/topic/242838
最后一个插件是我写的,在这里做个小小的广告,大家可以尝试着用用看,并提出宝贵意见。
在接下来的章节中,我会重点介绍Struts2中有关配置的详细内容、包括源码分析、简化配置的扩展点、自行编写插件来简化配置等等