??xml version="1.0" encoding="utf-8" standalone="yes"?>
1。不要用autowiring
Spring可以通过cȝ自省来自动绑定其依赖部分Q得你不必明确指明bean的属性和构造器。Bean的属性可以通过属性名U或cd匚w来实现自动绑定。构造器通过cd匚w来实现自动绑定。你甚至可以指定自动自动绑定模式,它可以引导Spring选择一U适当的运行机制。先来看看下面的一个例子:
OrderServicecȝ属性名在容器中用于匚wbean实例。自动绑定可以潜在地节省一些打字和减少一些乱。但是在现实世界的工E里你不应该使用q种方式Q这是因为它牺牲了配|的清晰性和可维护性。许多指南和介绍中大量吹捧自动绑定是Spring的一U极好的特征而没有提到这一Ҏ所带来的牺牌Ӏ依我的观点Q这像Spring中的objectQpoolingQ它更像是一Uؓ了占据更多市场的商业特征。它对于XML配置文g的小巧化是一个好办法Q但实际上也增加了复杂程度,其当你q行有大量类声明的工E时。虽然Spring允许你合自动绑定和手动l定Q但是这个矛盾会使XML配置更加晦ӆ难懂?
2.使用通俗的命?
q个方式对于Java~码也一样适用。在工程中用清晰的、描q性的、协调的通俗名称对于开发者理解XML配置是十分有益的。例如对于bean IDQ你可以Ҏ通俗的Javacd来命名它。对于例子中OrderServiceDAO的bean ID命名为orderServiceDAO。对于大的工E,你可以在bean ID前面加上包名作ؓ前缀?
3. 使用z的形式
zŞ式避免了冗长Q是因ؓ它从子元素中属性值和参考写到属性中。例如下面的例子Q?
可以使用zŞ式将上述代码重写为:
zŞ式功能在1.2版本中可以用。对?lt;ref local="...">没有zŞ式。简zŞ式不但可以节U你的打字,而且可以使XML配置文g清晰。它最引h注目的是当在一个配|文件中有大量定义的cL可以提高易读性?
4. 对于构造器参数匚wQ类型名比序号好?
当一个构造器含有一个以上的同种cd的参敎ͼ或者属性值的标签已经被占用时QSpring允许你用从0计数的序h解决q些会带来淆的问题。例如:
像下面这P利用cd属性来~写会更好一些:
使用索引可以E稍减少一些冗长,但是和用类型属性相比,它还是有Ҏ发生错误的們和难于阅ȝ~点。你应该只在构造器参数不明的时候,才用烦引这一Ҏ?
5. 可能重用已定义q的bean
Spring提供一U类似承一L机制来减配|信息的复制q简化XML配置。定义一个子cd以从它父c那里扉K|信息,而父cd质上作ؓ子类的一个模ѝ这是大工E中所谓的重用。你所需要做的就是在父类bean中设|abstract=trueQ然后在子bean注明它自q父类bean。例如:
ShippingServicecMabstractServicec那里承companyName属性的值——lizjason。如果你没有Z个bean指明cLfactoryҎQ那么这个bean便是抽象的?
6. 量使用ApplicationContext来装配定义的bean
像在Ant脚本中的引用一PSpring的引用对于装配模块化的bean来说是很有用的。例如:
相对于用import在XML配置中来预装配,通过ApplicationContext来配|这些beansQ显得更加灵zR利用ApplicationContext也得XML配置易于理。你可以像下面的例子那样在ApplictionContext构造器里布|beanQ?/p>
7. 利用id作ؓbean的标识符
你可以指定一个id或名U来作ؓbean的标识符。虽然用id不会提高易读性,但是它可以让XML parser对bean的引用有效方面进行更好的验证。如果由于XML IDREF的限制而不能用某个idQ你可以利用names来作为bean的标识符。XML IDREF的限制是id必须以字母开_或者在XML规范中定义的标点W号Q,后面接着字母Q数字,q字P下划U,冒号{。实际上Q遇到XML IDREF限制的问题是很少见的?
8. 在开发阶D用依赖检?
你可以在bean中给依赖验的属性设||而不采用原先默认的空|属性设|例如simpleQobject或allQ以便容器进行依赖检验。当bean的全部的属性(或某cd性)需要被明确讄或自动绑定时Q依赖检验便昑־很有用?
在这个例子里Q容器确保ؓorderService bean讄的属性不是primitives 或?collections。ؓ所有的bean讄默认依赖也是可以的Q但是我们很这样做Q是因ؓ有些bean的属性根本就不必讄?
9. 为每个配|文件加上一个header comment
最好用descriptive id和名U来代替在XML配置文g中的注释。此外,加上一个配|文件header也很有用处,它可以概q文件中所定义的bean。你可以选择描q内容加入description标签中。例如:
使用description标签的一个好处是可以Ҏ地利用工具从标签中选取出descriptionQ的内容Q?
10. 对于M变化Q要与队友积极交?
当你重构Java代码Ӟ你需要随时更新配|文件ƈ且通知队友。XML配置文g也是代码Q它们是应用E序的至关重要的部分Q但是它们难于阅dl护。大部分旉你既要阅读XML配置文g又要阅读q行中的Java代码?
11. Setter injection优于constructor injection
Spring提供3U类型的依赖注入Q?constructor injection,setter injection, 和method injection。我们一般只用前两种cd?
q个例子中,orderServicecM用的是constructor injectionQ而BillingServicecM用的是setter injection。constructor injection可以保bean不会在一个非法状态下被创建,但是setter injection更加灉|q且更易理Q尤其当cd在很多属性ƈ且其中一些是可选的情况下?
12. 不要滥用依赖注入
作ؓ最后一点,Spring ApplicationContext可以替你创徏Java对象Q但是ƈ不是所有的Java对象都通过依赖注入来创建的。例如,全局的对象不应该通过ApplicationContext来创建。Spring是一个很的框架Q但是,易L和易管理性而言Q当定义大量bean的时候,ZXML的配|问题就会突出。过度的依赖注入会XML配置变得复杂而且臃肿。记住!使用强大的IDEӞ例如Eclipse和IntelliJQ与XML文g相比QJava代码更加易读Q易l护Q易理?
ȝ
对于Spring的配|,XML是很优秀的方式。但当定义大量beanӞZXML配置会变得冗长,W拙。Spring提供了丰富的配置选项。适当地利用其中的选项可以使XML配置清晰Q但是,有些选项Q例如autowiringQ自动绑定)Q往往会降低易L和易维护性。文章中所列D的实例,可以帮助你创建出清晰易读的XML配置文g?br />
说实在的,q是很理惛_的设计方?真的,我的x也一?之所以是q样,主要是因为我看了一本Struts的书,是奥来理出版?里面是q样的一个概?虽然那本书里q没有严格按照这L思\来做.不过也可以看是很完美?但也是不可取的方?
不可取的地方在哪?性能问题,主要是从Service层上来的实体都可q行数据转换(DT),生成View层的DTO,单个实体是一ơ{?多个实体,比如set,iterator{?pnơ{?而这些仅仅是Z使视囑ֱ和Service层分?q是不明智的.
不过q样的模式的出现也是有原因的.因ؓ应用q个Service层可能会有多L客户?在适应多种客户端的p用到q些东西,比如客户端是一个Swing GUIE序?那么他需要的是一个序列化的数据包,而这个数据库仅仅列出的就是健值对,Z设计?q个客户端就不应该知道服务器端的cM及类的联p?它仅仅依赖于Service层提ȝDTO,那么p用到DTO,OK,现在明白robin的设计想法是相当合理,而且重用性很高的.q是大型J2EEE序所常用的方?
但对于专用于Web而永q不打算有其它客L的中WebE序来言,上面的方法已l有些不合时宜了,可以说没有必要死搬了.也就是说设计应该有所退?至于退化成什么样?是很让h觉得为难?我现在的思想?所有实体对象从最层的视囑ֱ到最底层的持久层,都是可以q?q样׃存在DT的问?那么中间q程是怎么L?
我的分法是这?
视图?br />-----
控制?br />-----
服务接口?br />-----
业务逻辑?br />-----
持久?br />-----
数据库层
I梭于其中的数据d是PO,也可以说它是VO.q些层从上往下依?比如说持久层依赖于数据库?如果数库的设计有所变化,必然会导x久层设计发生变化,而持久层也因此媄响业务逻辑?从而生骨牌效?虽然q样的设计是不好?但是谁能够解册L事情?数据库这h底层最核心的东襉K改变?q必然会影响整个E序的行?比如说数据库要求多加一个计录评分别的功能,可是原来的程序里没有q样的功?而且所有的调用接口都没有写到这斚w的功?那么不就是整个程序只要和q个功能有关的程序文仉要进行修?q是不可避免?如果可以避免,请告诉我Ҏ,弟永生C您的大恩).
Z么要分多一个服务接口层?很简?主要是把业务逻辑q特定的Web框架,不论是在Struts、Webwork、JSFQ他们都可正常运行,当然你也可以不要q一层,把业务逻辑写进ActionQ这样从而把E序Ll定C某个Web FrameworkQ这L好处是,E序的性能有很的提高Q不q苦果是Q某一天要Ҏ其它的Web framework呢?我徏议的Ҏ是加多一个服务接口层Q这样Action主要的Q务就是从接口层取得数据{到视囑ֱLC,q样Action的重d很清楚了Q它只是一个控制器而已Q笑话,那么q些自称MVC的框Ӟ启不只是VC而已Q哈…………)
那么什么是业务逻辑层呢Q因为程序ƈ不只是涉及数据库操作,而且怼伴随一些文件操?而这些都是对一实体的一ơ单元操?而且是可重用的操?业务逻辑层就是这L单元操作接口Q他调用持久层,更确切的说是DAOQ得到POQ但后进行相关的操作?/font>
注意Q这里的持久层不是具体到Hibernate的这些ORMQ而只是DAOQ具体的ORM由具体的DAO实现?/font>
c。。从上面q句话,也许你也会想问一个问题,具体的DAOQ对Q就是具体的DAO。这里就q用的面向接口编E的思想Q层与层之间调用的只是接口而已Q每一层都有特定的实现Q而这些特定的实现是可插拔的,而且不会影响原程序的q行。你可以用Factory模式生成具体的DAO beanQ呵…………这是一个痛苦的q程Q而且Factoryq样与程序逻辑无关的东西竟然一跃而上q入了我们的代码Q这不是一个好的方法,我们可以用一UIoC框架QSpring是一个极好的东西Q注入我们想要的DAO beanQ这h们写代码可以专心对接口~程了,我们没有必要担心什么Factory了,呵…?/font>
那么实体呢?他能接口化吗Q从我现在的所掌握的知识来看,他是不可接口化的Q他是数据的载体Q也是一些常规操作的载体Q也正是因ؓq样Q他是极光要也是极其简单的Q所以,他不用接口化?
好了Q终于理清这半年来所思考的东西了,大至上我已经明白怎样d理的规范化设计一个程序,现在剩下的只是挑选合适的应用框架Q然后做W一个Java Web开发。汗Q直到现在我都还没有真正开发过Java WebE序呢,呵………?/font>