簡化Spring(2)–Model層

來源:互聯網
上載者:User
    作者:江南白衣 

    因為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層

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.