日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring 中经典的 9 种设计模式,打死也要记住啊!

發布時間:2025/3/20 javascript 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring 中经典的 9 种设计模式,打死也要记住啊! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
點擊上方?好好學java?,選擇?星標?公眾號重磅資訊,干貨,第一時間送達今日推薦:分享一套基于SpringBoot和Vue的企業級中后臺開源項目,這個項目有點哇塞!個人原創100W +訪問量博客:點擊前往,查看更多

來源:blog.csdn.net/caoxiaohong1005

Spring中涉及的設計模式總結

1.簡單工廠(非23種設計模式中的一種)

實現方式:

BeanFactory。Spring中的BeanFactory就是簡單工廠模式的體現,根據傳入一個唯一的標識來獲得Bean對象,但是否是在傳入參數后創建還是傳入參數前創建這個要根據具體情況來定。

實質:

由一個工廠類根據傳入的參數,動態決定應該創建哪一個產品類。

實現原理:

bean容器的啟動階段:

  • 讀取bean的xml配置文件,將bean元素分別轉換成一個BeanDefinition對象。

  • 然后通過BeanDefinitionRegistry將這些bean注冊到beanFactory中,保存在它的一個ConcurrentHashMap中。

  • 將BeanDefinition注冊到了beanFactory之后,在這里Spring為我們提供了一個擴展的切口,允許我們通過實現接口BeanFactoryPostProcessor 在此處來插入我們定義的代碼。

    典型的例子就是:PropertyPlaceholderConfigurer,我們一般在配置數據庫的dataSource時使用到的占位符的值,就是它注入進去的。

容器中bean的實例化階段:

實例化階段主要是通過反射或者CGLIB對bean進行實例化,在這個階段Spring又給我們暴露了很多的擴展點:

  • 各種的Aware接口 ,比如 BeanFactoryAware,對于實現了這些Aware接口的bean,在實例化bean時Spring會幫我們注入對應的BeanFactory的實例。

  • BeanPostProcessor接口 ,實現了BeanPostProcessor接口的bean,在實例化bean時Spring會幫我們調用接口中的方法。

  • InitializingBean接口 ,實現了InitializingBean接口的bean,在實例化bean時Spring會幫我們調用接口中的方法。

  • DisposableBean接口 ,實現了BeanPostProcessor接口的bean,在該bean死亡時Spring會幫我們調用接口中的方法。

設計意義:

松耦合。 可以將原來硬編碼的依賴,通過Spring這個beanFactory這個工廠來注入依賴,也就是說原來只有依賴方和被依賴方,現在我們引入了第三方——spring這個beanFactory,由它來解決bean之間的依賴問題,達到了松耦合的效果.

bean的額外處理。 通過Spring接口的暴露,在實例化bean的階段我們可以進行一些額外的處理,這些額外的處理只需要讓bean實現對應的接口即可,那么spring就會在bean的生命周期調用我們實現的接口來處理該bean。[非常重要]

2.工廠方法

實現方式:

FactoryBean接口。

實現原理:

實現了FactoryBean接口的bean是一類叫做factory的bean。其特點是,spring會在使用getBean()調用獲得該bean時,會自動調用該bean的getObject()方法,所以返回的不是factory這個bean,而是這個bean.getOjbect()方法的返回值。

例子:

典型的例子有spring與mybatis的結合。

代碼示例:

說明:

我們看上面該bean,因為實現了FactoryBean接口,所以返回的不是 SqlSessionFactoryBean 的實例,而是它的 SqlSessionFactoryBean.getObject() 的返回值。

3.單例模式

Spring依賴注入Bean實例默認是單例的。

Spring的依賴注入(包括lazy-init方式)都是發生在AbstractBeanFactory的getBean里。getBean的doGetBean方法調用getSingleton進行bean的創建。

分析getSingleton()方法

public?Object?getSingleton(String?beanName){//參數true設置標識允許早期依賴return?getSingleton(beanName,true); } protected?Object?getSingleton(String?beanName,?boolean?allowEarlyReference)?{//檢查緩存中是否存在實例Object?singletonObject?=?this.singletonObjects.get(beanName);if?(singletonObject?==?null?&&?isSingletonCurrentlyInCreation(beanName))?{//如果為空,則鎖定全局變量并進行處理。synchronized?(this.singletonObjects)?{//如果此bean正在加載,則不處理singletonObject?=?this.earlySingletonObjects.get(beanName);if?(singletonObject?==?null?&&?allowEarlyReference)?{//當某些方法需要提前初始化的時候則會調用addSingleFactory?方法將對應的ObjectFactory初始化策略存儲在singletonFactoriesObjectFactory<?>?singletonFactory?=?this.singletonFactories.get(beanName);if?(singletonFactory?!=?null)?{//調用預先設定的getObject方法singletonObject?=?singletonFactory.getObject();//記錄在緩存中,earlysingletonObjects和singletonFactories互斥this.earlySingletonObjects.put(beanName,?singletonObject);this.singletonFactories.remove(beanName);}}}}return?(singletonObject?!=?NULL_OBJECT???singletonObject?:?null); }

getSingleton()過程圖

ps:spring依賴注入時,使用了 雙重判斷加鎖 的單例模式

總結

單例模式定義: 保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。

spring對單例的實現: spring中的單例模式完成了后半句話,即提供了全局的訪問點BeanFactory。但沒有從構造器級別去控制單例,這是因為spring管理的是任意的java對象。

4.適配器模式

實現方式:

SpringMVC中的適配器HandlerAdatper。

實現原理:

HandlerAdatper根據Handler規則執行不同的Handler。

實現過程:

DispatcherServlet根據HandlerMapping返回的handler,向HandlerAdatper發起請求,處理Handler。

HandlerAdapter根據規則找到對應的Handler并讓其執行,執行完畢后Handler會向HandlerAdapter返回一個ModelAndView,最后由HandlerAdapter向DispatchServelet返回一個ModelAndView。

實現意義:

HandlerAdatper使得Handler的擴展變得容易,只需要增加一個新的Handler和一個對應的HandlerAdapter即可。

因此Spring定義了一個適配接口,使得每一種Controller有一種對應的適配器實現類,讓適配器代替controller執行相應的方法。這樣在擴展Controller時,只需要增加一個適配器類就完成了SpringMVC的擴展了。

5.裝飾器模式

實現方式:

Spring中用到的包裝器模式在類名上有兩種表現:一種是類名中含有Wrapper,另一種是類名中含有Decorator。

實質:

動態地給一個對象添加一些額外的職責。

就增加功能來說,Decorator模式相比生成子類更為靈活。

6.代理模式

實現方式:

AOP底層,就是動態代理模式的實現。

動態代理:

在內存中構建的,不需要手動編寫代理類

靜態代理:

需要手工編寫代理類,代理類引用被代理對象。

實現原理:

切面在應用運行的時刻被織入。一般情況下,在織入切面時,AOP容器會為目標對象創建動態的創建一個代理對象。SpringAOP就是以這種方式織入切面的。

織入:把切面應用到目標對象并創建新的代理對象的過程。

7.觀察者模式

實現方式:

spring的事件驅動模型使用的是 觀察者模式 ,Spring中Observer模式常用的地方是listener的實現。

具體實現:

事件機制的實現需要三個部分,事件源,事件,事件監聽器

ApplicationEvent抽象類[事件]

繼承自jdk的EventObject,所有的事件都需要繼承ApplicationEvent,并且通過構造器參數source得到事件源.

該類的實現類ApplicationContextEvent表示ApplicaitonContext的容器事件.

代碼:

public?abstract?class?ApplicationEvent?extends?EventObject?{private?static?final?long?serialVersionUID?=?7099057708183571937L;private?final?long?timestamp;public?ApplicationEvent(Object?source)?{super(source);this.timestamp?=?System.currentTimeMillis();}public?final?long?getTimestamp()?{return?this.timestamp;} }

ApplicationListener接口[事件監聽器]

繼承自jdk的EventListener,所有的監聽器都要實現這個接口。

這個接口只有一個onApplicationEvent()方法,該方法接受一個ApplicationEvent或其子類對象作為參數,在方法體中,可以通過不同對Event類的判斷來進行相應的處理。

當事件觸發時所有的監聽器都會收到消息。

代碼:

public?interface?ApplicationListener<E?extends?ApplicationEvent>?extends?EventListener?{void?onApplicationEvent(E?event); }

ApplicationContext接口[事件源]

ApplicationContext是spring中的全局容器,翻譯過來是”應用上下文”。

實現了ApplicationEventPublisher接口。

職責:

負責讀取bean的配置文檔,管理bean的加載,維護bean之間的依賴關系,可以說是負責bean的整個生命周期,再通俗一點就是我們平時所說的IOC容器。

代碼:

public?interface?ApplicationEventPublisher?{void?publishEvent(ApplicationEvent?event); }public?void?publishEvent(ApplicationEvent?event)?{Assert.notNull(event,?"Event?must?not?be?null");if?(logger.isTraceEnabled())?{logger.trace("Publishing?event?in?"?+?getDisplayName()?+?":?"?+?event);}getApplicationEventMulticaster().multicastEvent(event);if?(this.parent?!=?null)?{this.parent.publishEvent(event);} }

ApplicationEventMulticaster抽象類[事件源中publishEvent方法需要調用其方法getApplicationEventMulticaster]

屬于事件廣播器,它的作用是把Applicationcontext發布的Event廣播給所有的監聽器.

代碼:

public?abstract?class?AbstractApplicationContext?extends?DefaultResourceLoaderimplements?ConfigurableApplicationContext,?DisposableBean?{private?ApplicationEventMulticaster?applicationEventMulticaster;protected?void?registerListeners()?{//?Register?statically?specified?listeners?first.for?(ApplicationListener<?>?listener?:?getApplicationListeners())?{getApplicationEventMulticaster().addApplicationListener(listener);}//?Do?not?initialize?FactoryBeans?here:?We?need?to?leave?all?regular?beans//?uninitialized?to?let?post-processors?apply?to?them!String[]?listenerBeanNames?=?getBeanNamesForType(ApplicationListener.class,?true,?false);for?(String?lisName?:?listenerBeanNames)?{getApplicationEventMulticaster().addApplicationListenerBean(lisName);}} }

8.策略模式

實現方式:

Spring框架的資源訪問Resource接口。該接口提供了更強的資源訪問能力,Spring 框架本身大量使用了 Resource 接口來訪問底層資源。

Resource 接口介紹

source 接口是具體資源訪問策略的抽象,也是所有資源訪問類所實現的接口。

Resource 接口主要提供了如下幾個方法:

  • getInputStream(): 定位并打開資源,返回資源對應的輸入流。每次調用都返回新的輸入流。調用者必須負責關閉輸入流。

  • exists(): 返回 Resource 所指向的資源是否存在。

  • isOpen(): 返回資源文件是否打開,如果資源文件不能多次讀取,每次讀取結束應該顯式關閉,以防止資源泄漏。

  • getDescription(): 返回資源的描述信息,通常用于資源處理出錯時輸出該信息,通常是全限定文件名或實際 URL。

  • getFile: 返回資源對應的 File 對象。

  • getURL: 返回資源對應的 URL 對象。

最后兩個方法通常無須使用,僅在通過簡單方式訪問無法實現時,Resource 提供傳統的資源訪問的功能。

Resource 接口本身沒有提供訪問任何底層資源的實現邏輯,針對不同的底層資源,Spring 將會提供不同的 Resource 實現類,不同的實現類負責不同的資源訪問邏輯。

Spring 為 Resource 接口提供了如下實現類:

  • UrlResource: 訪問網絡資源的實現類。

  • ClassPathResource: 訪問類加載路徑里資源的實現類。

  • FileSystemResource: 訪問文件系統里資源的實現類。

  • ServletContextResource: 訪問相對于 ServletContext 路徑里的資源的實現類.

  • InputStreamResource: 訪問輸入流資源的實現類。

  • ByteArrayResource: 訪問字節數組資源的實現類。

這些 Resource 實現類,針對不同的的底層資源,提供了相應的資源訪問邏輯,并提供便捷的包裝,以利于客戶端程序的資源訪問。

9.模版方法模式

經典模板方法定義:

父類定義了骨架(調用哪些方法及順序),某些特定方法由子類實現。

最大的好處:代碼復用,減少重復代碼。除了子類要實現的特定方法,其他方法及方法調用順序都在父類中預先寫好了。

所以父類模板方法中有兩類方法:

共同的方法: 所有子類都會用到的代碼

不同的方法: 子類要覆蓋的方法,分為兩種:

  • 抽象方法:父類中的是抽象方法,子類必須覆蓋

  • 鉤子方法:父類中是一個空方法,子類繼承了默認也是空的

注:為什么叫鉤子,子類可以通過這個鉤子(方法),控制父類,因為這個鉤子實際是父類的方法(空方法)!

Spring模板方法模式實質:

是模板方法模式和回調模式的結合,是Template Method不需要繼承的另一種實現方式。Spring幾乎所有的外接擴展都采用這種模式。

具體實現:

JDBC的抽象和對Hibernate的集成,都采用了一種理念或者處理方式,那就是模板方法模式與相應的Callback接口相結合。

采用模板方法模式是為了以一種統一而集中的方式來處理資源的獲取和釋放,以JdbcTempalte為例:

public?abstract?class?JdbcTemplate?{public?final?Object?execute(String?sql){Connection?con=null;Statement?stmt=null;try{con=getConnection();stmt=con.createStatement();Object?retValue=executeWithStatement(stmt,sql);return?retValue;}catch(SQLException?e){...}finally{closeStatement(stmt);releaseConnection(con);}}protected?abstract?Object?executeWithStatement(Statement???stmt,?String?sql); }

引入回調原因:

JdbcTemplate是抽象類,不能夠獨立使用,我們每次進行數據訪問的時候都要給出一個相應的子類實現,這樣肯定不方便,所以就引入了回調。

回調代碼

public?interface?StatementCallback{Object?doWithStatement(Statement?stmt); }

利用回調方法重寫JdbcTemplate方法

public?class?JdbcTemplate?{public?final?Object?execute(StatementCallback?callback){Connection?con=null;Statement?stmt=null;try{con=getConnection();stmt=con.createStatement();Object?retValue=callback.doWithStatement(stmt);return?retValue;}catch(SQLException?e){...}finally{closeStatement(stmt);releaseConnection(con);}}...//其它方法定義 }

Jdbc使用方法如下:

JdbcTemplate?jdbcTemplate=...;final?String?sql=...;StatementCallback?callback=new?StatementCallback(){public?Object=doWithStatement(Statement?stmt){return?...;} } jdbcTemplate.execute(callback);

為什么JdbcTemplate沒有使用繼承?

因為這個類的方法太多,但是我們還是想用到JdbcTemplate已有的穩定的、公用的數據庫連接,那么我們怎么辦呢?

我們可以把變化的東西抽出來作為一個參數傳入JdbcTemplate的方法中。但是變化的東西是一段代碼,而且這段代碼會用到JdbcTemplate中的變量。怎么辦?

那我們就用回調對象吧。在這個回調對象中定義一個操縱JdbcTemplate中變量的方法,我們去實現這個方法,就把變化的東西集中到這里了。然后我們再傳入這個回調對象到JdbcTemplate,從而完成了調用。

推薦文章
  • 今天給大家推薦6個Spring Boot項目,拿來就可以賺錢!

  • 分享一套基于SpringBoot和Vue的企業級中后臺開源項目,這個項目有點哇塞!

  • 圈子哥推薦一種基于Spring Boot開發OA開源產品,學習/搞外快都是不二選擇!

  • 硬剛一周,3W字總結,一年的經驗告訴你如何準備校招!

原創電子書歷時整整一年總結的?Java面試+ Java入門技術學習指南,這是本人這幾年及校招的總結,各種異步面試題已經全部進行總結,按照章節復習即可,已經拿到了了大廠提供。原創思維導圖 掃碼或者微信搜?程序員的技術圈子?回復?面試?領取原創電子書和思維導圖。

總結

以上是生活随笔為你收集整理的Spring 中经典的 9 种设计模式,打死也要记住啊!的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 一区二区人妻 | 久久久午夜影院 | 91亚洲精华 | 男女裸体无遮挡做爰 | 91在线视频观看 | 非洲一级黄色片 | 久久综合色婷婷 | 黄色片网站免费在线观看 | 日韩中文字幕精品 | 久艹在线播放 | 久久久久久国产视频 | 女女调教被c哭捆绑喷水百合 | 久久精品欧美一区二区三区麻豆 | 久久久久亚洲av无码a片 | 超碰97av | 亚洲AV无码精品一区二区三区 | 国产网站黄 | 久久99九九| 国产精品视频一区二区三区不卡 | 18无码粉嫩小泬无套在线观看 | 少妇扒开粉嫩小泬视频 | 深爱婷婷网 | 中文字幕日韩精品在线 | 亚洲女人的天堂 | 日本三级视频网站 | 亚洲视频日韩 | 国产伦理一区二区三区 | 成人欧美一区二区三区白人 | 黄色网久久 | www..com黄色 | 欧洲精品视频在线观看 | www.激情五月 | 一级美女黄色片 | 丰满岳妇伦在线播放 | 亚洲另类色图 | 欧美一区二区高清视频 | 婷婷色中文 | 精品玖玖玖| 国产欧美在线一区 | 久久影院午夜理论片无码 | 精品中出 | 伊人久久大香网 | 亚洲成人伦理 | 欧美色狠| 亚洲国产高清国产精品 | 青青草成人在线 | 国产伦精品一区二区三区 | 日韩免费大片 | 亚洲男女啪啪 | 57pao国产精品一区 | 四虎综合网 | 国产三级精品三级在线观看 | 国产成人视屏 | 亚洲av无码乱码在线观看性色 | 天天插美女 | 一级做a爱片久久毛片 | 嫩草视频一区二区三区 | 久久久久久久免费 | 肉丝超薄少妇一区二区三区 | 亚洲激情二区 | 一级国产特黄bbbbb | 特黄aaaaaaa片免费视频 | 欧美粗又大| 一色屋免费视频 | 久久澡 | 香蕉网在线视频 | 小柔的淫辱日记(h | www.日本精品 | 欧美精品久久久久久久自慰 | 国产欧美精品国产国产专区 | 黄色网日本 | 人人搞人人干 | 国产精品视频专区 | 亚洲综合久久网 | 十八禁一区二区三区 | 日韩av资源在线观看 | 日日射av| 久久国产电影 | 操少妇视频| 国产日本在线观看 | 久久9966| 精品人人人 | 哺乳期给上司喂奶hd | 中文字幕第一页在线 | 第五色婷婷 | 亚洲男人天堂网址 | 欧美乱妇日本无乱码特黄大片 | 日韩av一区二区三区在线观看 | 91视频二区 | 三级黄在线观看 | 伊人ab | 国产精品扒开腿做爽爽爽男男 | 国产a区| 日本a视频在线观看 | 亚洲精品无码久久久久久久 | 国产精品视频a | 亚洲不卡视频在线 | www.成人免费 | 国产黄色91 |