2010-04-17 74 views
5

我可以做春季服務班嗎?這樣做有什麼害處嗎?沒有人會延長課程。有什麼問題嗎?使Spring服務類最終?

public final class MyService { 
    // Depedencies go here. 
} 

回答

14

不要讓它們成爲final。如果您在具體類上使用任何AOP(包括事務支持),spring將使用CGLIB動態擴展您的類以創建代理。而CGLIB的工作要求是讓你的課程不是final。否則會拋出異常。

+0

很好的答案。所以DAO類可以是「最終」的?它們通常不是交易型的。 – fastcodejava 2010-04-17 18:41:29

+2

嗯,然後_can_,但也要小心。你可能會在某些時候爲它們添加一些AOP。 – Bozho 2010-04-18 06:08:21

+1

這些工具的缺陷是無法對最終的類進行測試,這對於正確的面向對象設計是必須的(例如,參見「實用API設計」一書或甚至是GoF書)。 *有*方法來測試最終課程;像CGLIB這樣的工具已經過時了。 – 2011-05-19 12:27:39

4

春將創建一個JDK動態代理,而不是CGLIB代理,如果滿足下列條件:

  1. AOP:配置具有代理目標類設置爲false
  2. 任何其他命名空間配置(例如TX :事務管理)也有代理的目標類設置爲false
  3. 你的類實現一個接口

如果所有三個屬實,那麼你可以聲明類決賽。 (如果你喜歡,你甚至可以將類包私有和構造函數私有化,Spring將能夠實例化它)。

否則,Spring將創建一個CGLIB代理。如果bean中沒有公共方法,您仍然可以聲明類最終(假定它未用@Repository修飾,並且沒有聲明PersistenceExceptionPostBeanProcessor)。一旦你有一個單一的公共方法,你就不能用CBLIB代理來聲明類的最終結果。 (注意:當通過CGLIB進行代理時,您必須至少有一個包私有的,無參數的構造函數)。

以上什麼時候有用?假設你有一個服務接口(所有的服務通常應該有接口)和一個封裝私有的實現bean。該服務正在使用JDK動態代理。因此,它可能是最終的並且在包之外是不可見的,泄漏的實現細節較少。說服務需要一個數據訪問對象。如果沒有其他服務使用此DAO,爲什麼要將它或其任何方法公開?如果DAO上的所有方法都是包私有的,那麼服務實現仍然可以連接DAO並使用它的方法。從包外,調用者只能看到接口(一件好事)和接口簽名中使用的任何類型。

最後(沒有雙關語意),儘可能做出最後一堂課。具體的繼承往往混淆了被濫用(見fragile base problem)。最終類還允許進行一些編譯器優化。