如果僅僅是想學會使用,則可以不學習設計模式,如果想深入層次的學習Spring底層源碼,則設計模式是必不可少的!
下面從幾個方面進行介紹
(1) Spring 源碼中使用了哪些設計模式?
(2) 怎樣學習設計模式?
(3) 推薦設計模式的書籍
Spring源碼中使用了哪些設計模式?spring 中使用了多種設計模式,下面簡單介紹一下主要的設計模式
(1) 單例模式
保證獨一無二,為了提高資源重復利用,通過技術手段保證在整個系統運行階段,只有一個實例
場景: 配置文件、監控程序、IOC 容器、日歷
實現手段: 懶漢式、餓漢式、注冊登記式、反序列處理
Spring最常用的,注冊登記式,效率性能最高的
Spring中bean的默認作用域就是singleton(單例)。
實現方式:
xml : <bean id="userService" class="top.snailclimb.UserService" scope="singleton"/>注解:@Scope(value = "singleton")Spring 通過 ConcurrentHashMap 實現單例注冊表的特殊方式實現單例模式。Spring 實現單例的核心代碼如下
(2) 代理設計模式
代理模式在 AOP 中的應用
AOP(Aspect-Oriented Programming:面向切面編程)能夠將那些與業務無關,卻為業務模塊所共同調用的邏輯或責任(例如事務處理、日志管理、權限控制等)封裝起來,便于減少系統的重復代碼,降低模塊間的耦合度,并有利于未來的可拓展性和可維護性。
Spring AOP 就是基于動態代理的,如果要代理的對象,實現了某個接口,那么Spring AOP會使用JDK Proxy,去創建代理對象,而對于沒有實現接口的對象,就無法使用 JDK Proxy 去進行代理了,這時候Spring AOP會使用Cglib ,這時候Spring AOP會使用 Cglib 生成一個被代理對象的子類來作為代理,如下圖所示:
當然你也可以使用 AspectJ ,Spring AOP 已經集成了AspectJ ,AspectJ 應該算的上是 Java 生態系統中最完整的 AOP 框架了。
使用 AOP 之后我們可以把一些通用功能抽象出來,在需要用到的地方直接使用即可,這樣大大簡化了代碼量。我們需要增加新功能時也方便,這樣也提高了系統擴展性。日志功能、事務管理等等場景都用到了 AOP 。
Spring AOP 和 AspectJ AOP 有什么區別?
Spring AOP 屬于運行時增強,而 AspectJ 是編譯時增強。 Spring AOP 基于代理(Proxying),而 AspectJ 基于字節碼操作(Bytecode Manipulation)。
Spring AOP 已經集成了 AspectJ ,AspectJ 應該算的上是 Java 生態系統中最完整的 AOP 框架了。AspectJ 相比于 Spring AOP 功能更加強大,但是 Spring AOP 相對來說更簡單,
如果我們的切面比較少,那么兩者性能差異不大。但是,當切面太多的話,最好選擇 AspectJ ,它比Spring AOP 快很多。
(3) 模板方法
應用場景: JdbcTemplate 工作流
代碼場景: 模擬Spring JdbcTemplate的簡單實現
Spring 中 jdbcTemplate、hibernateTemplate 等于 Template 結尾的對數據庫操作的類,它們就使用到了模板模式。一般情況下,我們都是使用繼承的方式來實現模板模式,但是 Spring 并沒有使用這種方式,而是使用Callback 模式與模板方法模式配合,既達到了代碼復用的效果,同時增加了靈活性。
(4) 觀察者模式
觀察者模式是一種對象行為型模式。它表示的是一種對象與對象之間具有依賴關系,當一個對象發生改變的時候,這個對象所依賴的對象也會做出反應。Spring 事件驅動模型就是觀察者模式很經典的一個應用。Spring 事件驅動模型非常有用,在很多場景都可以解耦我們的代碼。比如我們每次添加商品的時候都需要重新更新商品索引,這個時候就可以利用觀察者模式來解決這個問題。
Spring 事件驅動模型中的三種角色
事件角色
ApplicationEvent (org.springframework.context包下)充當事件的角色,這是一個抽象類,它繼承了java.util.EventObject并實現了 java.io.Serializable接口。
Spring 中默認存在以下事件,他們都是對 ApplicationContextEvent 的實現(繼承自ApplicationContextEvent):
ContextStartedEvent:ApplicationContext 啟動后觸發的事件;ContextStoppedEvent:ApplicationContext 停止后觸發的事件;ContextRefreshedEvent:ApplicationContext 初始化或刷新完成后觸發的事件;ContextClosedEvent:ApplicationContext 關閉后觸發的事件。事件監聽者角色
ApplicationListener 充當了事件監聽者角色,它是一個接口,里面只定義了一個 onApplicationEvent()方法來處理ApplicationEvent。ApplicationListener接口類源碼如下,可以看出接口定義看出接口中的事件只要實現了 ApplicationEvent就可以了。所以,在 Spring中我們只要實現 ApplicationListener 接口實現 onApplicationEvent() 方法即可完成監聽事件
事件發布者角色
ApplicationEventPublisher 充當了事件的發布者,它也是一個接口。ApplicationEventPublisher 接口的publishEvent()這個方法在AbstractApplicationContext類中被實現,閱讀這個方法的實現,你會發現實際上事件真正是通過ApplicationEventMulticaster來廣播出去的。具體內容過多,就不在這里分析了,后面可能會單獨寫一篇文章提到。
Spring 的事件流程總結
定義一個事件: 實現一個繼承自 ApplicationEvent,并且寫相應的構造函數;
定義一個事件監聽者:實現 ApplicationListener 接口,重寫 onApplicationEvent() 方法;
使用事件發布者發布消息: 可以通過 ApplicationEventPublisher 的 publishEvent() 方法發布消息。
Example:
(5) 適配器模式
適配器模式(Adapter Pattern) 將一個接口轉換成客戶希望的另一個接口,適配器模式使接口不兼容的那些類可以一起工作,其別名為包裝器(Wrapper)。
spring AOP中的適配器模式
我們知道 Spring AOP 的實現是基于代理模式,但是 Spring AOP 的增強或通知(Advice)使用到了適配器模式,與之相關的接口是AdvisorAdapter 。Advice 常用的類型有:BeforeAdvice(目標方法調用前,前置通知)、AfterAdvice(目標方法調用后,后置通知)、AfterReturningAdvice(目標方法執行結束后,return之前)等等。每個類型Advice(通知)都有對應的攔截器:MethodBeforeAdviceInterceptor、AfterReturningAdviceAdapter、AfterReturningAdviceInterceptor。Spring預定義的通知要通過對應的適配器,適配成 MethodInterceptor接口(方法攔截器)類型的對象(如:MethodBeforeAdviceInterceptor 負責適配 MethodBeforeAdvice)。
代碼場景:登錄,為了兼容舊系統的登錄功能,在老系統的基礎之上進行兼容編程,Spring Adapter結尾的
(6) 裝飾器模式
裝飾者模式可以動態地給對象添加一些額外的屬性或行為。相比于使用繼承,裝飾者模式更加靈活。簡單點兒說就是當我們需要修改原有的功能,但我們又不愿直接去修改原有的代碼時,設計一個Decorator套在原有代碼外面。其實在 JDK 中就有很多地方用到了裝飾者模式,比如 InputStream家族,InputStream 類下有 FileInputStream (讀取文件)、BufferedInputStream (增加緩存,使讀取文件速度大大提升)等子類都在不修改InputStream 代碼的情況下擴展了它的功能
應用場景: IO流 、數據源、也用代碼改造一個舊系統,在Spring 中Decorator結尾的,Wrapper結尾的都是。
(7) 委派模式
代理模式的特殊情況,全權代理
應用場景: 項目經理、Dispatcher
代碼場景: Spring 中ServletDispatcher /Delegate 命名結尾的都是委派模式
怎樣學習設計模式(1) 調整好心態,不要指望一蹴而就,不可浮躁。
學習和掌握設計模式需要一個過程,不同的階段看這些設計模式有不同的領悟和感受。不要指望真正的設計模式的書籍既簡單又有趣,一看就懂的。
(2) 學習設計模式的第一步 : 準確理解每個設計模式的功能、基本結構、標準實現,了解適合使用它的場景以及使用的效果。
(3) 學習設計模式的第二步: 實際的開發中,嘗試著使用這些設計模式,并反復思考和總結是否使用得當,是否需要做一些變化。
(4) 學習設計模式的第三步 : 再回頭去看設計模式的理論,有了實際的模式應用經驗再看設計模式,會有不同的感悟,一邊看一邊結合著應用經驗來思考。比如設計模式的本質功能是什么?它是如何實現的?z這種實現方式還可以在什么地方應用? 如何才能把這個設計模式和具體的應用結合起來?這個設計模式的出發點是什么?等等。可以有很多考慮的點,從不同的角度對設計模式進行思考。
(5) 第四步 : 多次反復學習設計模式的第二步和第三步。也就是在實際開發中使用,然后結合理論思考,然后再應用,再思考...如此循環,反復多次,直到達到對設計模式基本掌握的水平。
簡而言之,要注意使用設計模式的理論和實踐相結合,理論指導實踐,實踐反過來加深對理論的理解,如此反復循環,成螺旋式上升!
設計模式書籍的推薦這本書非常經典,大家可以反復閱讀,由于網上已沒有紙質書,只有電子版,
有需要電子版的,可以私信。