posts - 20,  comments - 2,  trackbacks - 0

          作者: tianshi0253  鏈接:http://tianshi0253.javaeye.com/blog/202860  發表時間: 2008年06月13日

          聲明:本文系JavaEye網站發布的原創博客文章,未經作者書面許可,嚴禁任何網站轉載本文,否則必將追究法律責任!

           因為Spring自帶的sample離我們的實際項目很遠,所以官方一點的model層模式展現就靠Appfuse了。
              但Appfuse的model層總共有一個DAO接口、一個DAOImpl類、一個Service接口、一個ServiceImpl類、一個DataObject.....大概只有受慣了虐待的人才會欣然接受吧。
              另外,Domain-Driven逢初一、十五也會被拿出來討論一遍。

              其實無論什么模式,都不過是一種人為的劃分、抽象和封裝。只要在團隊里理解一致,自我感覺優雅就行了。
               我的建議是,一開始DO和Manager一生一旦包演全場,DO作為純數據載體,而Manager類放置商業方法,用getHibernateTemplate()直接訪問數據庫,不強制基于接口編程。當某天系統復雜到你直覺上需要將DAO層和Service層分開時,再分開就好了。

              1.DataObject類
              
          好聽點也可以叫Domain Object。Domain Driven  Development雖然誘人,但因為Java下的ORM框架都是基于Data Mapper模式的,沒有Ruby On Rails中那種Active Recorder的模式。所以,還是壓下了這個欲望,Data Object純粹作一個數據載體,而把數據庫訪問與商業邏輯操作統一放到Manager類中。

              2.Manager類
              我的Manager類是Appfuse中DAO類與Service類的結合體,因為:

              2.1 不想使用純DAO
               以往的DAO是為了透明不同數據庫間的差異,而現在Hibernate已經做的很好。所以目前純DAO的更大作用是為了將來可以切換到別的ORM方案比如iBatis,但一個Pragmaic的程序員顯然不會無聊到為了這個機會不大的理由,現在就去做一個純DAO層,項目又不是Appfuse那樣為了demo各種ORM方案而存在。

              2.2 也不想使用Service層來為Dao解耦
              在JPetStore里有一個很薄的Service層,Fascade了一堆DAO類,把這些DAO類的所有方法都僵硬的重復了一遍。理論上一個Manager類可以管理數個Dao類,可以避免Dao之間直接耦合。但既然有Manager的情況下,商業邏輯都是寫在Manager類的,那樣子Manager似乎還是調用另一個Manager比較妥當,調用裸Dao可能存在忽略了某些邏輯。所以,耦合又從Dao層升到Service層了。
               所以,除非你做的是超薄的不帶邏輯的Service層,否則沒有解耦的意義。
              何況,對一個不是死搬書的Designer來說,組件邊界之內的類之間的耦合并不是耦合。

              3.去除不必要的基于接口編程
              眾所周知,Spring是提倡基于接口編程的。
              但有些Manager類,比如SaleOrderManager ,只有5%的機會再有另一個Impl實現。95%時間里這兩兄弟站一起,就像C++里的.h和.cpp,徒增維護的繁瑣(經常要同步兩個文件的函數聲明),和代碼瀏覽跳轉時的不便(比如從Controler類跟蹤到Service類時,只能跳轉到接口類的相應函數,還要再按一次復雜的熱鍵才跳轉到實現類)
              連Martin Flower都說,強制每個類都分離接口和實現是過猶不及。只在有多個獨立實現,或者需要消除對實現類的依賴時,才需要分離接口。

              3.1 DAO被強制用接口的原因
              Spring IOC本身是不會強制基于接口的,但DAO類一般要使用Spring的聲明式事務機制,而聲明式的事務機制是使用Spring AOP來實現的。Spring AOP的實現機制包括動態代理和Cgilib2,其中Spring AOP默認使用的Java動態代理是必須基于接口,所以就要求基于接口了。
              
              3.2 解決方法
              那就讓Spring AOP改用CGLib2,生成目標類的子類吧,我們只要指定使用聲明式事務的FactoryBean使用CGLib的方式來實現AOP,就可以不基于接口編程了。
              指定的方式為設置proxyTargetClass為true。如下:

          <bean class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
          id="baseService"   abstract="true">
           <property name="transactionManager" ref="transactionManager"/>
           <property name="proxyTargetClass" value="true"/>
          
          </bean>

           
               又因為這些Service Bean都是單例,效率應該不受影響。

              4.總結
              對比Appfuse里面的5個類,我的Model層里只有VO作為純數據載體,Manager類放商業方法。有人說這樣太簡單了,但一個應用,要劃成幾個JSP,一個Controller,一個Manager,一個VO,對我來說已經足夠復雜,再要往上架墻疊屋,恕不奉陪,起碼在我的項目范圍里不需要。(但有很多項目是需要的,神佑世人)

              后記:迫于世人的壓力,SpringSide暫時還是把DAO和Service層分開了,但依然堅持不搞那么多接口。
          另外,盡量利用IDEA的代碼生成熱鍵,為Manager類生成delegate的Dao類方法。

           

          相關文章:

          簡化Spring(1)--配置文件

          簡化Spring(2)--Model層

          簡化Spring(3)--Controller層

          簡化Spring(4)--View層

           


          本文的討論也很精彩,瀏覽討論>>


          JavaEye推薦




          文章來源:http://tianshi0253.javaeye.com/blog/202860
          posted on 2008-06-13 10:58 姚文超 閱讀(54) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 疏附县| 巫山县| 万州区| 双鸭山市| 方城县| 鄂托克旗| 丰县| 县级市| 甘南县| 银川市| 湖北省| 兴安盟| 济阳县| 旺苍县| 彝良县| 巍山| 高清| 布尔津县| 清徐县| 多伦县| 黑山县| 会昌县| 肃宁县| 靖远县| 萨嘎县| 广东省| 杭锦后旗| 交口县| 措勤县| 滁州市| 抚宁县| 赤壁市| 怀来县| 靖边县| 泰顺县| 驻马店市| 嘉峪关市| 淮北市| 安龙县| 积石山| 凌海市|