最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解讀Spring框架中常用的設(shè)計(jì)模式

 更新時(shí)間:2022年12月23日 16:19:25   作者:chao09_01  
這篇文章主要介紹了解讀Spring框架中常用的設(shè)計(jì)模式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

一、淺談控制反轉(zhuǎn)(IOC)與依賴注入(DI)

IOC(Inversion of Control)是Spring中一個(gè)非常重要的概念,它不是什么技術(shù),而是一種解耦的設(shè)計(jì)思想。

它主要的額目的是借助于第三方(Spring中的IOC容器)實(shí)現(xiàn)具有依賴關(guān)系的的對象之間的解耦(IOC容易管理對象,你只管使用即可),從而降低代碼之間的耦合度。

它不是一個(gè)模式,而是一種設(shè)計(jì)原則,但以下模式(但不限于)實(shí)現(xiàn)了IOC的設(shè)計(jì)原則。

補(bǔ)充:對控制反轉(zhuǎn)的理解:

舉個(gè)例子“對象A依賴了對象B,當(dāng)對象A需要使用對象B的時(shí)候必須自己去創(chuàng)建。

但是當(dāng)系統(tǒng)引入了IOC容器后,對象A和對象B之前就失去了直接的聯(lián)系。

這個(gè)時(shí)候,當(dāng)對象A需要使用對象B的時(shí)候,我們可以指定IOC容器去創(chuàng)建一個(gè)對象B注入到對象A中”。

對象A獲得對象B的過程,由主動行為變成了被動行為,控制權(quán)實(shí)現(xiàn)了反轉(zhuǎn),這就是控制反轉(zhuǎn)名字的由來。

DI(Dependency Inject)依賴注入實(shí)現(xiàn)控制反轉(zhuǎn)的的一種實(shí)現(xiàn)方式,依賴注入就是將實(shí)例變量傳入到一個(gè)對象中去。

二、Spring框架中的設(shè)計(jì)模式

1)工廠設(shè)計(jì)模式(簡單工廠和工廠方法)

Spring使用工廠模式可以通過BeanFactory或ApplicationContext創(chuàng)建bean對象。

兩者對比:

  • BeanFactory:延遲注入(使用到某個(gè) bean 的時(shí)候才會注入),相比于BeanFactory來說會占用更少的內(nèi)存,程序啟動速度更快。
  • ApplicationContext:容器啟動的時(shí)候,不管你用沒用到,一次性創(chuàng)建所有 bean 。BeanFactory 僅提供了最基本的依賴注入支持,ApplicationContext 擴(kuò)展了 BeanFactory ,除了有BeanFactory的功能還有額外更多功能,所以一般開發(fā)人員使用ApplicationContext會更多。

2)單例設(shè)計(jì)模式

Spring中bean的默認(rèn)作用域就是singleton。

除了singleton作用域,Spring bean還有下面幾種作用域:

  • prototype:每次請求都會創(chuàng)建一個(gè)新的 bean 實(shí)例。
  • request:每一次HTTP請求都會產(chǎn)生一個(gè)新的bean,該bean僅在當(dāng)前HTTP request內(nèi)有效。
  • session:每一次HTTP請求都會產(chǎn)生一個(gè)新的 bean,該bean僅在當(dāng)前 HTTP session 內(nèi)有效。
  • global-session:全局session作用域,僅僅在基于portlet的web應(yīng)用中才有意義,Spring5已經(jīng)沒有了。Portlet是能夠生成語義代碼(例如:HTML)片段的小型Java Web插件。它們基于portlet容器,可以像servlet一樣處理HTTP請求。但是,與 servlet 不同,每個(gè) portlet 都有不同的會話。

Spring實(shí)現(xiàn)單例的方式:

xml格式:

<bean id="userService" class="top.snailclimb.UserService" scope="singleton"/>

注解:

@Scope(value = "singleton")

Spring通過ConcurrentHashMap實(shí)現(xiàn)單例注冊表的特殊方式實(shí)現(xiàn)單例模式。

Spring實(shí)現(xiàn)單例的核心代碼如下:

// 通過 ConcurrentHashMap(線程安全) 實(shí)現(xiàn)單例注冊表  
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);  
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {  
        Assert.notNull(beanName, "'beanName' must not be null");  
        synchronized (this.singletonObjects) {  
            // 檢查緩存中是否存在實(shí)例    
            Object singletonObject = this.singletonObjects.get(beanName);  
            if (singletonObject == null) {  
                //...省略了很多代碼  
                try {  
                    singletonObject = singletonFactory.getObject();  
                }  
                //...省略了很多代碼  
                // 如果實(shí)例對象在不存在,我們注冊到單例注冊表中。  
                addSingleton(beanName, singletonObject);  
            }  
            return (singletonObject != NULL_OBJECT ? singletonObject : null);  
        }  
    }  
    //將對象添加到單例注冊表  
    protected void addSingleton(String beanName, Object singletonObject) {  
            synchronized (this.singletonObjects) {  
                this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));  
            }  
        }  
} 

3)代理設(shè)計(jì)模式

Spring AOP就是基于動態(tài)代理的,如果要代理的對象,實(shí)現(xiàn)了某個(gè)接口,那么Spring AOP會使用JDK Proxy,去創(chuàng)建代理對象,而對于沒有實(shí)現(xiàn)接口的對象,就無法使用JDK Proxy去進(jìn)行代理了,這時(shí)候Spring AOP會使用Cglib,這時(shí)候Spring AOP會使用Cglib生成一個(gè)被代理對象的子類來作為代理。

如下圖所示:

當(dāng)然你也可以使用AspectJ,Spring AOP已經(jīng)繼承了AspectJ,AspectJ應(yīng)該算的上是java生態(tài)系統(tǒng)中最完整的AOP框架了。

Spring AOP和AspectJ AOP有什么區(qū)別?

Spring AOP屬于運(yùn)行時(shí)增強(qiáng),而AspectJ是編譯時(shí)增強(qiáng)。Spring AOP基于代理,而AspectJ基于字節(jié)碼操作。

Spring AOP已經(jīng)集成了AspectJ,AsectJ應(yīng)該算的上是Java生態(tài)系統(tǒng)中最完整的AOP框架了。

AspectJ相比于Spring AOP功能更加強(qiáng)大,但是Spring AOP相對來說更簡單,如果我們的切面比較少,那么兩者的性能差異不大。

但是當(dāng)切面太多的話,最好選擇AspectJ,它比Spring AOP快很多。

4)模板方法設(shè)計(jì)模式

模板方法模式是一種行為設(shè)計(jì)模式,它定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中。

模板方法使得子類可以在不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的默寫特定步驟的實(shí)現(xiàn)方式。

例如:

public abstract class Template {  
    //這是我們的模板方法  
    public final void TemplateMethod(){  
        PrimitiveOperation1();    
        PrimitiveOperation2();  
        PrimitiveOperation3();  
    }  
    protected void  PrimitiveOperation1(){  
        //當(dāng)前類實(shí)現(xiàn)  
    }  
    //被子類實(shí)現(xiàn)的方法  
    protected abstract void PrimitiveOperation2();  
    protected abstract void PrimitiveOperation3();  
}  
public class TemplateImpl extends Template {  
    @Override  
    public void PrimitiveOperation2() {  
        //當(dāng)前類實(shí)現(xiàn)  
    }  
    @Override  
    public void PrimitiveOperation3() {  
        //當(dāng)前類實(shí)現(xiàn)  
    }  
} 

Spring中jdbcTemplate、hibernateTemplate等以Template結(jié)尾的對數(shù)據(jù)庫操作的類,它們就使用到模板模式。

一般情況下,我們都是使用繼承的方式來實(shí)現(xiàn)模板模式,但是Spring并沒有使用這種方式,而是使用Callback模式與模板方法配合,既達(dá)到了代碼復(fù)用的效果,同時(shí)增加了靈活性。

5)觀察者設(shè)計(jì)模式

觀察者設(shè)計(jì)模式是一種對象行為模式。它表示的是一種對象與對象之間具有依賴關(guān)系,當(dāng)一個(gè)對象發(fā)生改變時(shí),這個(gè)對象鎖依賴的對象也會做出反應(yīng)。Spring事件驅(qū)動模型就是觀察者模式很經(jīng)典的應(yīng)用。

事件角色:ApplicationEvent(org.springframework.context包下)充當(dāng)事件的角色,這是一個(gè)抽象類。

事件監(jiān)聽者角色:ApplicationListener充當(dāng)了事件監(jiān)聽者的角色,它是一個(gè)接口,里面只定義了一個(gè)onApplicationEvent()方法來處理ApplicationEvent。

事件發(fā)布者角色:ApplicationEventPublisher充當(dāng)了事件的發(fā)布者,它也是個(gè)接口。

Spring事件流程總結(jié):

  • 定義一個(gè)事件: 實(shí)現(xiàn)一個(gè)繼承自 ApplicationEvent,并且寫相應(yīng)的構(gòu)造函數(shù);
  • 定義一個(gè)事件監(jiān)聽者:實(shí)現(xiàn) ApplicationListener 接口,重寫 onApplicationEvent() 方法;
  • 使用事件發(fā)布者發(fā)布消息: 可以通過 ApplicationEventPublisher 的 publishEvent() 方法發(fā)布消息。

例如:

// 定義一個(gè)事件,繼承自ApplicationEvent并且寫相應(yīng)的構(gòu)造函數(shù)  
public class DemoEvent extends ApplicationEvent{  
    private static final long serialVersionUID = 1L;  
    private String message;  
    public DemoEvent(Object source,String message){  
        super(source);  
        this.message = message;  
    }  
    public String getMessage() {  
         return message;  
          }  
// 定義一個(gè)事件監(jiān)聽者,實(shí)現(xiàn)ApplicationListener接口,重寫 onApplicationEvent() 方法;  
@Component  
public class DemoListener implements ApplicationListener<DemoEvent>{  
    //使用onApplicationEvent接收消息  
    @Override  
    public void onApplicationEvent(DemoEvent event) {  
        String msg = event.getMessage();  
        System.out.println("接收到的信息是:"+msg);  
    }  
}  
// 發(fā)布事件,可以通過ApplicationEventPublisher  的 publishEvent() 方法發(fā)布消息。  
@Component  
public class DemoPublisher {  
    @Autowired  
    ApplicationContext applicationContext;  
    public void publish(String message){  
        //發(fā)布事件  
        applicationContext.publishEvent(new DemoEvent(this, message));  
    }  
} 

6)適配器設(shè)計(jì)模式

適配器設(shè)計(jì)模式將一個(gè)接口轉(zhuǎn)換成客戶希望的另一個(gè)接口,適配器模式使得接口不兼容的那些類可以一起工作,其別名為包裝器。

在Spring MVC中,DispatcherServlet根據(jù)請求信息調(diào)用HandlerMapping,解析請求對應(yīng)的Handler,解析到對應(yīng)的Handler(也就是我們常說的Controller控制器)后,開始由HandlerAdapter適配器處理。

為什么要在Spring MVC中使用適配器模式?

Spring MVC中的Controller種類眾多不同類型的Controller通過不同的方法來對請求進(jìn)行處理,有利于代碼的維護(hù)拓展。

7)裝飾者設(shè)計(jì)模式

裝飾者設(shè)計(jì)模式可以動態(tài)地給對象增加些額外的屬性或行為。

相比于使用繼承,裝飾者模式更加靈活。

Spring 中配置DataSource的時(shí)候,DataSource可能是不同的數(shù)據(jù)庫和數(shù)據(jù)源。

我們能否根據(jù)客戶的需求在少修改原有類的代碼下切換不同的數(shù)據(jù)源?

這個(gè)時(shí)候據(jù)需要用到裝飾者模式。

8)策略設(shè)計(jì)模式

Spring 框架的資源訪問接口就是基于策略設(shè)計(jì)模式實(shí)現(xiàn)的。該接口提供了更強(qiáng)的資源訪問能力,Spring框架本身大量使用了Resource接口來訪問底層資源。

Resource接口本身沒有提供訪問任何底層資源的實(shí)現(xiàn)邏輯,針對不同的額底層資源,Spring將會提供不同的Resource實(shí)現(xiàn)類,不同的實(shí)現(xiàn)類負(fù)責(zé)不同的資源訪問類型。

Spring 為 Resource 接口提供了如下實(shí)現(xiàn)類: 

  • UrlResource:訪問網(wǎng)絡(luò)資源的實(shí)現(xiàn)類。
  • ClassPathResource:訪問類加載路徑里資源的實(shí)現(xiàn)類。
  • FileSystemResource:訪問文件系統(tǒng)里資源的實(shí)現(xiàn)類。
  • ServletContextResource:訪問相對于 ServletContext 路徑里的資源的實(shí)現(xiàn)類.
  • InputStreamResource:訪問輸入流資源的實(shí)現(xiàn)類。
  • ByteArrayResource:訪問字節(jié)數(shù)組資源的實(shí)現(xiàn)類。 

這些 Resource 實(shí)現(xiàn)類,針對不同的的底層資源,提供了相應(yīng)的資源訪問邏輯,并提供便捷的包裝,以利于客戶端程序的資源訪問。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Spring中如何動態(tài)注入Bean實(shí)例教程

    Spring中如何動態(tài)注入Bean實(shí)例教程

    這篇文章主要給大家介紹了關(guān)于Spring中如何動態(tài)注入Bean的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-12-12
  • java 多線程的幾種實(shí)現(xiàn)方法總結(jié)

    java 多線程的幾種實(shí)現(xiàn)方法總結(jié)

    這篇文章主要介紹了java 多線程的幾種實(shí)現(xiàn)方法總結(jié)的相關(guān)資料,希望通過本文能幫助到大家,讓大家掌握java多線程的知識,需要的朋友可以參考下
    2017-10-10
  • 解決 java.lang.NoSuchMethodError的錯(cuò)誤

    解決 java.lang.NoSuchMethodError的錯(cuò)誤

    這篇文章主要介紹了解決 java.lang.NoSuchMethodError的錯(cuò)誤的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • JavaWeb實(shí)現(xiàn)用戶登錄與注冊功能(服務(wù)器)

    JavaWeb實(shí)現(xiàn)用戶登錄與注冊功能(服務(wù)器)

    這篇文章主要介紹了JavaWeb實(shí)現(xiàn)用戶登錄與注冊功能,服務(wù)器部分的關(guān)鍵代碼實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • LIS 最長遞增子序列 Java的簡單實(shí)現(xiàn)

    LIS 最長遞增子序列 Java的簡單實(shí)現(xiàn)

    下面小編就為大家?guī)硪黄狶IS 最長遞增子序列 Java的簡單實(shí)現(xiàn)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-09-09
  • 詳解使用Mybatis-plus + velocity模板生成自定義的代碼

    詳解使用Mybatis-plus + velocity模板生成自定義的代碼

    這篇文章主要介紹了詳解使用Mybatis-plus + velocity模板生成自定義的代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Project?Reactor源碼解析publishOn使用示例

    Project?Reactor源碼解析publishOn使用示例

    這篇文章主要為大家介紹了Project?Reactor源碼解析publishOn使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • 關(guān)于Jar包部署命令全面解析

    關(guān)于Jar包部署命令全面解析

    這篇文章主要介紹了Jar包部署命令全面解析,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Java讀取properties文件之中文亂碼問題及解決

    Java讀取properties文件之中文亂碼問題及解決

    這篇文章主要介紹了Java讀取properties文件之中文亂碼問題及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 在Java中輕松將HTML格式文本轉(zhuǎn)換為純文本的方法示例(保留換行)

    在Java中輕松將HTML格式文本轉(zhuǎn)換為純文本的方法示例(保留換行)

    這篇文章主要介紹了在Java中輕松將HTML格式文本轉(zhuǎn)換為純文本的方法示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04

最新評論

奉新县| 祁东县| 凌海市| 东海县| 桐柏县| 岑溪市| 雅安市| 南江县| 浦江县| 屏南县| 平顶山市| 墨脱县| 延长县| 冷水江市| 西安市| 邻水| 浏阳市| 南昌县| 香格里拉县| 汉川市| 兴和县| 延安市| 横峰县| 轮台县| 信阳市| 娱乐| 博白县| 永靖县| 寿宁县| 桂平市| 贞丰县| 即墨市| 阿坝| 滁州市| 丹巴县| 尼玛县| 且末县| 阿克苏市| 隆安县| 哈巴河县| 汾西县|