成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

論 Spring 框架所運(yùn)用的設(shè)計(jì)模式

開(kāi)發(fā)
本文直接從底層源碼設(shè)計(jì)和實(shí)現(xiàn)的角度,詳盡分析了 Spring 中涉及的設(shè)計(jì)模式,希望對(duì)你有幫助。

在當(dāng)今軟件開(kāi)發(fā)的廣闊領(lǐng)域中,Spring 框架無(wú)疑占據(jù)著重要的一席之地。它以其強(qiáng)大的功能和靈活性,成為眾多開(kāi)發(fā)者的得力助手。而在 Spring 框架的背后,蘊(yùn)含著一系列精妙絕倫的設(shè)計(jì)模式,這些設(shè)計(jì)模式猶如隱藏的智慧密碼,賦予了框架無(wú)盡的活力與魅力。

當(dāng)我們深入探究 Spring 框架時(shí),就仿佛開(kāi)啟了一扇通往軟件設(shè)計(jì)藝術(shù)殿堂的大門(mén)。其中的設(shè)計(jì)模式不僅是代碼組織和架構(gòu)的精巧構(gòu)建,更是對(duì)軟件開(kāi)發(fā)理念的深刻詮釋。它們巧妙地解決了各種復(fù)雜問(wèn)題,實(shí)現(xiàn)了代碼的高效復(fù)用、模塊的松散耦合以及系統(tǒng)的良好擴(kuò)展性。通過(guò)對(duì) Spring 框架涉及的設(shè)計(jì)模式的剖析,我們將領(lǐng)略到設(shè)計(jì)智慧的熠熠光輝,感受它們?nèi)绾卧谲浖澜缰醒堇[出一場(chǎng)場(chǎng)精彩絕倫的代碼之舞,為構(gòu)建高質(zhì)量、可維護(hù)的軟件系統(tǒng)奠定堅(jiān)實(shí)基礎(chǔ)。讓我們一同踏上這場(chǎng)探索 Spring 框架設(shè)計(jì)模式的奇妙之旅,去揭示其中的奧秘與精彩。

一、關(guān)于設(shè)計(jì)模式的一些只是鋪墊

1.軟件設(shè)計(jì)有哪些原則?

整體來(lái)說(shuō)有七大原則:

  • 開(kāi)閉原則:對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉。
  • 里氏轉(zhuǎn)換:子類(lèi)繼承父類(lèi)時(shí),除添加新的方法完成新增功能外,盡量不要重寫(xiě)父類(lèi)的方法。
  • 依賴(lài)倒置: 高層類(lèi)應(yīng)該依賴(lài)于底層類(lèi)的抽象而不是具體。
  • 合成復(fù)用:盡量使用對(duì)象組合/聚合,而不是繼承關(guān)系達(dá)到軟件復(fù)用的目的。
  • 單一職責(zé):不要多于一個(gè)導(dǎo)致類(lèi)變更的原因。
  • 接口原則:用多個(gè)接口確定類(lèi)的行為,而不是一個(gè)總接口定義所有行為。
  • 迪米特法則:最少知道原則,一個(gè)類(lèi)應(yīng)該盡可能減少對(duì)其他類(lèi)的了解,避免類(lèi)之間過(guò)度耦合。(其他類(lèi)應(yīng)該封裝一個(gè)方法提供的該類(lèi)使用)

2.設(shè)計(jì)模式分為哪幾類(lèi)?有哪些設(shè)計(jì)模式

分類(lèi):

  • 創(chuàng)建型模式:創(chuàng)建型模式主要用于創(chuàng)建對(duì)象。
  • 結(jié)構(gòu)型模式:主要用于處理類(lèi)或?qū)ο蟮慕M合。
  • 行為型模式:主要用于描述對(duì)類(lèi)或?qū)ο笤鯓咏换ズ驮鯓臃峙渎氊?zé)。

創(chuàng)建型模式:

  • 單例模式:確保類(lèi)有且只有一個(gè)對(duì)象被創(chuàng)建。
  • 抽象工廠模式:允許客戶(hù)創(chuàng)建對(duì)象的宗族,而無(wú)需指定他們的具體類(lèi)。
  • 建造者模式:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離,讓同樣的構(gòu)建過(guò)程而已創(chuàng)建不同的表示。
  • 工廠方法模式:由類(lèi)決定要?jiǎng)?chuàng)建的具體類(lèi)是哪一個(gè)。
  • 原型模式:用原型實(shí)例指定創(chuàng)建對(duì)象的種類(lèi),并且通過(guò)拷貝這個(gè)原型來(lái)創(chuàng)建新的對(duì)象。

結(jié)構(gòu)型模式:

  • 適配器模式:封裝對(duì)象,并提供不同的接口。
  • 橋接模式:將抽象部分和實(shí)現(xiàn)部分分離,讓他們獨(dú)立的變化。
  • 裝飾模式:包裝一個(gè)對(duì)象,提供新的行為。
  • 組合模式:客戶(hù)用一致的方式處理對(duì)象集合和單個(gè)對(duì)象。
  • 外觀模式:簡(jiǎn)化一群類(lèi)的接口。
  • 享元模式:運(yùn)用共享技術(shù)有效的支持大量細(xì)粒度的對(duì)象。
  • 代理模式:包裝對(duì)象,以控制對(duì)此對(duì)象的訪問(wèn)。

行為型模式:

  • 模板方法模式:定義一個(gè)操作算法的總體架構(gòu),將一些步驟的實(shí)現(xiàn)放在子類(lèi)中。
  • 命令模式:封裝請(qǐng)求成為對(duì)象。
  • 迭代器模式:在對(duì)象的集合之中游走,而不是暴露集合的實(shí)現(xiàn)。
  • 觀察者模式:讓對(duì)象能夠在狀態(tài)改變時(shí)被通知。
  • 中介者模式:用一個(gè)中介對(duì)象來(lái)封裝一系列的對(duì)象交互。中介者使各個(gè)對(duì)象不需要顯示的相互引用,從而使其耦合松散,而且可以獨(dú)立地改變他們之間的交互。
  • 備忘錄模式:在不破壞封裝性的前提下,捕獲一個(gè)對(duì)象的內(nèi)部狀態(tài),并在該對(duì)象之外保存這個(gè)狀態(tài)。 以后就可以將該對(duì)象恢復(fù)到保存狀態(tài)。
  • 解釋器模式:介紹給定一個(gè)語(yǔ)言,定義它的文法的一種表示,并定義一個(gè)解釋器, 該解釋器使用該表示來(lái)解釋語(yǔ)言中的句子。
  • 狀態(tài)模式:封裝了基于狀態(tài)的行為,并使用委托在行為之間的切換。
  • 策略模式:封裝可以互換的行為,并使用委托來(lái)決定要使用哪一個(gè)。
  • 責(zé)任鏈模式:為了解除請(qǐng)求的發(fā)送者和接收者之間的耦合,使多個(gè)對(duì)象都有機(jī)會(huì)處理這個(gè)請(qǐng)求。將這些處理對(duì)象連成一個(gè)鏈,并沿著這個(gè)鏈傳遞該請(qǐng)求,直到一個(gè)對(duì)象處理它。
  • 訪問(wèn)者模式:一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作。它使你可以在不改變各元素的類(lèi)的前提下定義作用于這些元素的新操作。

二、詳解Spring核心中的設(shè)計(jì)模式

1.為什么說(shuō)Spring框架中的IOC是解耦的

從代碼層面來(lái)說(shuō),Spring通過(guò)控制反轉(zhuǎn)將對(duì)象之類(lèi)依賴(lài)關(guān)系交由容器管理,如下所示我們的AService  依賴(lài)BService ,BService 可能還會(huì)依賴(lài)于CService 層層遞進(jìn),如果是傳統(tǒng)編碼,我們可能需要通過(guò)硬編碼的方式完成AService  的構(gòu)建。 而Spring通過(guò)IOC思想,在初始化階段將所有對(duì)象都交由三級(jí)緩存管理,將所有java bean初始化責(zé)任的實(shí)現(xiàn)細(xì)節(jié)轉(zhuǎn)移給Spring,使用時(shí)也只需指明接口類(lèi)型,接口實(shí)現(xiàn)也無(wú)需關(guān)心,只需在配置層面中指定,而非通過(guò)硬編碼完成依賴(lài)管理:

所以我們使用時(shí)只需幾個(gè)簡(jiǎn)單的配置和注解即可完成各種復(fù)雜的bean的依賴(lài)管理,這也就是開(kāi)發(fā)層面對(duì)象依賴(lài)關(guān)系管理的解耦:

@Service("aService")
@Slf4j
public class AService  {

    @Autowired
    private BService bService;

   //......

}

從使用層面來(lái)說(shuō),Spring中的IOC也用到類(lèi)似于門(mén)面模式的思想,將工具類(lèi)的使用和創(chuàng)建剝離,整個(gè)工具類(lèi)的創(chuàng)建過(guò)程對(duì)使用者來(lái)說(shuō)是透明解耦的。

例如我們需要使用日志框架,在spring中我們只需給出簡(jiǎn)單的配置,框架即在運(yùn)行時(shí)基于給定配置完成對(duì)應(yīng)的日志工具的注入(可以是log4j可以是slf4j或者其他日志框架),程序啟動(dòng)后即可直接使用功能,無(wú)需關(guān)心創(chuàng)建和實(shí)現(xiàn):

2.Spring源碼中涉及的簡(jiǎn)單工廠模式

簡(jiǎn)單工廠模式的思想就是對(duì)外屏蔽創(chuàng)建對(duì)象的細(xì)節(jié),將對(duì)象的獲取統(tǒng)一內(nèi)聚到一個(gè)工廠類(lèi)中,這一點(diǎn)在Spring中的ApplicationContext 發(fā)揮的淋漓盡致。 我們都知道Spring將所有java bean統(tǒng)一交由三級(jí)緩存進(jìn)行管理,使用時(shí)我們可以通過(guò)上下文或者需要的java bean,用戶(hù)只需按需要傳遞給工廠對(duì)應(yīng)的bean名稱(chēng)即可得到自己需要的對(duì)象即可:

對(duì)應(yīng)的我們也給出使用示例:

@Autowired
    private ApplicationContext applicationContext;

    public Object getBean(String beanName) {
        Object bean = applicationContext.getBean(beanName);
        return bean;
    }

3.Spring中的工廠方法模式

工廠方法模式適用于想讓工廠專(zhuān)注創(chuàng)建一個(gè)對(duì)象的場(chǎng)景,相較于簡(jiǎn)單工廠模式,工廠方法模式思想是提供一個(gè)工廠的接口,開(kāi)發(fā)者根據(jù)這個(gè)規(guī)范創(chuàng)建不同的工廠,然后按需使用不同的工廠創(chuàng)建不同的類(lèi)即可。這種做法確保了工廠類(lèi)也遵循開(kāi)閉原則。

Spring中的FactoryBean就是工廠方法模式的典型實(shí)現(xiàn),如果我們希望容器中能夠提供一個(gè)可以創(chuàng)造指定類(lèi)的工廠,那么我們就可以通過(guò)FactoryBean實(shí)現(xiàn)。 例如我們希望有一個(gè)工廠可以創(chuàng)建經(jīng)理,另一個(gè)工廠可以創(chuàng)建主管。那么我們就可以通過(guò)FactoryBean實(shí)現(xiàn)。 實(shí)現(xiàn)步驟如下,由于經(jīng)理和主管都是雇員類(lèi),所以我們創(chuàng)建一個(gè)雇員類(lèi):

//雇員類(lèi)
public class EmployeeDTO {

 private Integer id;
 private String firstName;
 private String lastName;
 private String designation;

 //Setters and Getters are hidden behind this comment.


 public Integer getId() {
  return id;
 }

 public void setId(Integer id) {
  this.id = id;
 }

 public String getFirstName() {
  return firstName;
 }

 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }

 public String getLastName() {
  return lastName;
 }

 public void setLastName(String lastName) {
  this.lastName = lastName;
 }

 public String getDesignation() {
  return designation;
 }

 public void setDesignation(String designation) {
  this.designation = designation;
 }

 @Override
 public String toString() {
  return "Employee [id=" + id + ", firstName=" + firstName
    + ", lastName=" + lastName + ", type=" + designation + "]";
 }
}

然后我們繼承FactoryBean接口實(shí)現(xiàn)一個(gè)工廠方法類(lèi),如下所示,可以看到如果我們可以根據(jù)傳入的designation決定創(chuàng)建的雇員類(lèi)型。

public class EmployeeFactoryBean extends AbstractFactoryBean<Object> {
 // 根據(jù)這個(gè)值決定創(chuàng)建主管還是經(jīng)理
 private String designation;

 public String getDesignation() {
  return designation;
 }

 public void setDesignation(String designation) {
  this.designation = designation;
 }

 //This method will be called by container to create new instances
 @Override
 protected Object createInstance() throws Exception {
  EmployeeDTO employee = new EmployeeDTO();
  employee.setId(-1);
  employee.setFirstName("dummy");
  employee.setLastName("dummy");
  //Set designation here
  employee.setDesignation(designation);
  return employee;
 }

 //This method is required for autowiring to work correctly
 @Override
 public Class<EmployeeDTO> getObjectType() {
  return EmployeeDTO.class;
 }
}

兩種雇員的配置如下所示:

<!--factoryBean使用示例-->
<!--經(jīng)理工廠-->
 <bean id="manager"  class="com.study.service.EmployeeFactoryBean">
  <property name="designation" value="Manager" />
 </bean>
<!--主管工廠-->
 <bean id="director"  class="com.study.service.EmployeeFactoryBean">
  <property name="designation" value="Director" />
 </bean>

如果我們想創(chuàng)建director(主管)的工廠,那么我們的代碼就可以這樣使用,注意我們獲取bean時(shí)必須使用&,否則獲得的就不是EmployeeFactoryBean,則是EmployeeDTO

ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
  Object factory =  context.getBean("&director");
  System.out.println(factory);
  //工廠方法模式,通過(guò)單一職責(zé)的工廠獲取專(zhuān)門(mén)的類(lèi)
  System.out.println(((EmployeeFactoryBean) factory).getObject());

當(dāng)然,如果想直接獲取高管或者經(jīng)理,獲取bean時(shí)不加&即可代碼如下所示即可:

ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

  EmployeeDTO manager = (EmployeeDTO) context.getBean("manager");
  System.out.println(manager);

  Object director =  context.getBean("director");
  System.out.println(director);

4.工廠方法模式相較于簡(jiǎn)單工廠模式的優(yōu)缺點(diǎn)

工廠方法模式的優(yōu)點(diǎn):

  • 符合開(kāi)閉原則,相較于上面說(shuō)到的簡(jiǎn)單工廠模式來(lái)說(shuō),我們無(wú)需因?yàn)樵黾右粋€(gè)類(lèi)型而去修改工廠代碼,我們完全可以通過(guò)實(shí)現(xiàn)一個(gè)新的工廠實(shí)現(xiàn)。
  • 更符合單一職責(zé)的原則,對(duì)于單個(gè)類(lèi)型創(chuàng)建的工廠邏輯更加易于維護(hù)。

缺點(diǎn):

  • 針對(duì)特定類(lèi)型都需要?jiǎng)?chuàng)建特定工廠,創(chuàng)建的類(lèi)會(huì)增加,導(dǎo)致項(xiàng)目變得臃腫。
  • 因?yàn)楣S方法的模式結(jié)構(gòu),維護(hù)的成本相對(duì)于簡(jiǎn)單工廠模式會(huì)更高一些。

5.單例模式在Java中的使用優(yōu)勢(shì)

節(jié)省沒(méi)必要的創(chuàng)建對(duì)象的時(shí)間,由于是單例的對(duì)象,所以創(chuàng)建一次后就可以一直使用了,所以我們無(wú)需為了一個(gè)重量級(jí)對(duì)象的創(chuàng)建而耗費(fèi)大量的資源。

由于重量級(jí)對(duì)象的創(chuàng)建次數(shù)少了,所以我們就避免了沒(méi)必要的GC。從而降低GC壓力,避免沒(méi)必要的STW(Stop the World)導(dǎo)致的GC停頓。

6.Spring中單例模式的實(shí)現(xiàn)

Spring中獲取對(duì)象實(shí)例的方法即DefaultSingletonBeanRegistry中的getSingleton就是典型的Double-Checked Locking單例模式代碼:

@Nullable
 protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  // Quick check for existing instance without full singleton lock
  Object singletonObject = this.singletonObjects.get(beanName);
  //一級(jí)緩存沒(méi)有需要的bean,進(jìn)入該邏輯
  if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
   singletonObject = this.earlySingletonObjects.get(beanName);
   if (singletonObject == null && allowEarlyReference) {
    //二級(jí)對(duì)象也沒(méi)有,上鎖進(jìn)入創(chuàng)建邏輯
    synchronized (this.singletonObjects) {
     // 再次檢查一級(jí)緩存也沒(méi)有,避免重復(fù)創(chuàng)建問(wèn)題
     singletonObject = this.singletonObjects.get(beanName);
     if (singletonObject == null) {
      //......
      //創(chuàng)建對(duì)象存入二級(jí)緩存中
      }
     }
    }
   }
  }
  return singletonObject;
 }

7.Spring中的代理模式

代理模式解耦了調(diào)用者和被調(diào)用者的關(guān)系,同時(shí)通過(guò)對(duì)原生類(lèi)型的代理進(jìn)行增強(qiáng)易于拓展和維護(hù),Spring AOP就是通過(guò)代理模式實(shí)現(xiàn)增強(qiáng)切入,我們就以JDK代理為例查看Spring中的實(shí)現(xiàn):

public Object getProxy(@Nullable ClassLoader classLoader) {
  // 忽略代碼
  Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
  findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
  //通過(guò)被代理的類(lèi)的接口以及增強(qiáng)邏輯創(chuàng)建一個(gè)增強(qiáng)的用戶(hù)所需要的類(lèi)
  return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
 }

查看newProxyInstance的實(shí)現(xiàn)即可看到j(luò)dk代理的傳統(tǒng)創(chuàng)建細(xì)節(jié)即拿到被代理的類(lèi)類(lèi)型和需要增強(qiáng)后的方法實(shí)現(xiàn)InvocationHandler 通過(guò)反射完成代理類(lèi)創(chuàng)建:

@CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
     //......
       //獲取接口類(lèi)類(lèi)型
        Class<?> cl = getProxyClass0(loader, intfs);

      //......
      //從緩存中獲取代理類(lèi)的構(gòu)造方法
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
           //......
           //基于InvocationHandler 和構(gòu)造方法完成代理類(lèi)創(chuàng)建
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
           //......
        } catch (InvocationTargetException e) {
           //......
        } catch (NoSuchMethodException e) {
            throw new InternalError(e.toString(), e);
        }
    }

8.Spring中的模板方法模式

模板方法模式即固定一個(gè)算法骨架,抽象出某些可變的方法交給子類(lèi)實(shí)現(xiàn),Spring的AbstractApplicationContext的refresh方法就是典型模板方法模式,

@Override
 public void refresh() throws BeansException, IllegalStateException {
  // 給容器refresh加鎖,避免容器處在refresh階段時(shí),容器進(jìn)行了初始化或者銷(xiāo)毀的操作
  synchronized (this.startupShutdownMonitor) {
   // .........

   try {
    // .........
    //定義了相關(guān)接口給用戶(hù)實(shí)現(xiàn),該方法會(huì)通過(guò)回調(diào)的方式調(diào)用這些方法,已經(jīng)實(shí)現(xiàn)好的細(xì)節(jié)
    invokeBeanFactoryPostProcessors(beanFactory);

    // 注冊(cè)攔截bean創(chuàng)建過(guò)程的BeanPostProcessor,已經(jīng)實(shí)現(xiàn)好的細(xì)節(jié)
    registerBeanPostProcessors(beanFactory);

    //模板方法的體現(xiàn),用戶(hù)可自定義重寫(xiě)該方法
    onRefresh();

    //.......
   }

   // .......
  }
 }

9.模板方法模式的優(yōu)劣勢(shì)

優(yōu)勢(shì)很明顯:

  • 算法骨架由父類(lèi)定義,封裝不變,擴(kuò)展可變。
  • 子類(lèi)只需按需實(shí)現(xiàn)抽象類(lèi)即可,易于擴(kuò)展維護(hù)。
  • 提取了公共代碼,避免編寫(xiě)重復(fù)代碼。

缺點(diǎn):

  • 可讀性下降
  • 可能會(huì)導(dǎo)致子類(lèi)泛濫問(wèn)題。

10.Spring中的觀察者模式

觀察者模式是一種行為型模式。 它表示的是一種主題與訂閱者之間具有依賴(lài)關(guān)系,當(dāng)訂閱者訂閱的主題狀態(tài)發(fā)生改變,會(huì)發(fā)送通知給響應(yīng)訂閱者,觸發(fā)訂閱者的響應(yīng)操作。

Spring 事件驅(qū)動(dòng)模型就是觀察者模式很經(jīng)典的一個(gè)應(yīng)用。Spring 事件驅(qū)動(dòng)模型非常有用,在很多場(chǎng)景都可以解耦我們的代碼。比如我們每次發(fā)布一個(gè)通知就需要某個(gè)用戶(hù)做出收到的響應(yīng),這個(gè)時(shí)候就可以利用觀察者模式來(lái)解決這個(gè)問(wèn)題。

首先我們需要定義一個(gè)事件類(lèi):

public class DemoEvent extends ApplicationEvent {
    private String msg;

    public DemoEvent(Object source, String msg) {
        super(source);
        this.msg = msg;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

然后創(chuàng)建一個(gè)監(jiān)聽(tīng)器集成Spring框架的ApplicationListener,對(duì)DemoEvent進(jìn)行監(jiān)聽(tīng):

@Component
public class DemoListener implements ApplicationListener<DemoEvent> {
    private static Logger logger = LoggerFactory.getLogger(DemoListener.class);

    @Override
    public void onApplicationEvent(DemoEvent event) {

        logger.info("收到消息,消息內(nèi)容:{}", event.getMsg());
    }
}

這樣我們發(fā)布事件后,監(jiān)聽(tīng)器就接受并處理返回結(jié)果了:

@Autowired
    private ApplicationContext applicationContext;


  @Test
    public void sendMsg() {
        DemoEvent event = new DemoEvent(this, "你好");
        applicationContext.publishEvent(event);
    }

對(duì)應(yīng)輸出結(jié)果如下所示:

2022-11-22 13:03:15.814  INFO 15600 --- [           main] com.example.demo.DemoListener            : 收到消息,消息內(nèi)容:你好

11.Spring中用到的適配器模式

適配器模式有用在在DisposableBeanAdapter適配統(tǒng)一處理bean銷(xiāo)毀上,因?yàn)槲覀僢ean銷(xiāo)毀方法可以通過(guò)xml配置也可以通過(guò)繼承DisposableBean接口實(shí)現(xiàn),所以這兩種不同的方法在銷(xiāo)毀時(shí)處理方式可能不一樣,所以我們可以通過(guò)適配器模式將這兩個(gè)處理邏輯封裝成統(tǒng)一適配器進(jìn)行處理

@Override
 public void destroy() {
  //......
  //如果是接口實(shí)現(xiàn)則執(zhí)行該類(lèi)實(shí)現(xiàn)的destroy方法
  if (this.invokeDisposableBean) {
   //......
   try {
    if (System.getSecurityManager() != null) {
    //......
    }
    else {
    //
     ((DisposableBean) this.bean).destroy();
    }
   }
   catch (Throwable ex) {
    //......
   }
  }
  
  //如果有注解或者xml配置的方法,則走invokeCustomDestroyMethod進(jìn)行調(diào)用
  if (this.destroyMethod != null) {
   invokeCustomDestroyMethod(this.destroyMethod);
  }
  else if (this.destroyMethodName != null) {
   Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
   if (methodToInvoke != null) {
    invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
   }
  }
 }

12.Spring中的裝飾者模式

裝飾者模式即通過(guò)組合的方式對(duì)原有類(lèi)的行為進(jìn)行一些擴(kuò)展操作即在開(kāi)閉原則下的一種結(jié)構(gòu)型設(shè)計(jì)模式,就以Spring中的TransactionAwareCacheDecorator為例,它就是實(shí)現(xiàn)緩存支持事務(wù)的功能,繼承緩存接口,并將目標(biāo)緩存類(lèi)組合進(jìn)來(lái),保證原有類(lèi)不被修改的情況下實(shí)現(xiàn)功能的擴(kuò)展:

//繼承Cache 類(lèi)
public class TransactionAwareCacheDecorator implements Cache {

 //行為需要擴(kuò)展的目標(biāo)類(lèi)
 private final Cache targetCache;



// 從接口那里獲得的put方法,通過(guò)對(duì)targetCache的put進(jìn)行進(jìn)一步封裝實(shí)現(xiàn)功能的包裝
 @Override
 public void put(final Object key, @Nullable final Object value) {
  if (TransactionSynchronizationManager.isSynchronizationActive()) {
   TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
    @Override
    public void afterCommit() {
     TransactionAwareCacheDecorator.this.targetCache.put(key, value);
    }
   });
  }
  else {
   this.targetCache.put(key, value);
  }
 }

}

三、更多關(guān)于設(shè)計(jì)模式

1.什么是策略模式

策略模式是一種行為模式,它的作用主要是用于封裝那些動(dòng)作一致,但是具體實(shí)現(xiàn)不一致的場(chǎng)景。例如我們現(xiàn)在有一個(gè)審核的動(dòng)作,不同的人審核的方式不同。而且審核的行為會(huì)隨著時(shí)間推移不斷增加,單純使用if else去維護(hù)會(huì)使得代碼變得非常凌亂。 這時(shí)候使用策略模式定義一下相同的行為,讓子類(lèi)去實(shí)現(xiàn)不同的策略,這樣的方式是最利于拓展的。

2.策略模式在Spring中如何使用

使用策略模式前,我們先需要使用接口固定一下策略的定義,例如我們現(xiàn)在要?jiǎng)?chuàng)建一個(gè)生成對(duì)象的策略createObj:

public interface CreateObjStrategy {

    Object createObj();
}

對(duì)應(yīng)我們分別寫(xiě)一個(gè)創(chuàng)建字符串對(duì)象和json對(duì)象的策略代碼:

@Component("createObj_str")
public class CreateStrObjStrategy implements CreateObjStrategy {
    @Override
    public Object createObj() {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "xiaoming");
        return JSONUtil.toJsonStr(map);
    }
}

@Component("createObj_json")
public class CreateJsonObjStrategy implements CreateObjStrategy {
    @Override
    public Object createObj() {
        JSONObject obj = new JSONObject();
        obj.put("name", "zhangsan");
        return obj;
    }
}

到此為止,我們已經(jīng)完成了所有的策略的封裝,按照原生的策略模式的做法它會(huì)通過(guò)一個(gè)上下文來(lái)配置當(dāng)前策略,就像下面這張?jiān)O(shè)計(jì)圖:

對(duì)應(yīng)我們給出封裝的代碼示例:

public class CreateJsonObjContext {

    private CreateObjStrategy createObjStrategy;

    public CreateJsonObjContext(CreateObjStrategy strategy) {
        this.createObjStrategy = strategy;
    }


    public Object createObj() {
        return createObjStrategy.createObj();
    }


}

實(shí)際上有了Spring我們無(wú)需進(jìn)行顯示聲明創(chuàng)建了,我們可以通過(guò)配置、注解等方式指明本地程序需要注入的CreateObjStrategy 實(shí)現(xiàn),加載上下文的時(shí)候通過(guò)ApplicationContextAware這樣的擴(kuò)展點(diǎn)把bean取出來(lái)設(shè)置到CreateJsonObjContext 中:

@Component
public class CreateJsonObjContext implements ApplicationContextAware {

    private CreateObjStrategy createObjStrategy;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        //從容器中拿到由我們配置后容器中所設(shè)置的CreateObjStrategy設(shè)置到Context中
        CreateObjStrategy bean = applicationContext.getBean(CreateObjStrategy.class);
        createObjStrategy = bean;
    }

    public Object createObj() {
        return createObjStrategy.createObj();
    }

    
}

3.Spring中策略模式的運(yùn)用

最典型的就時(shí)InstantiationStrategy,Spring為其實(shí)現(xiàn)了兩種不同的策略,分別是CglibSubclassingInstantiationStrategy和SimpleInstantiationStrategy,在Spring通過(guò)實(shí)例化java bean的時(shí)候其內(nèi)部就會(huì)通過(guò)getInstantiationStrategy從上下文中獲取初始化策略instantiationStrategy,然后調(diào)用instantiationStrategy的instantiate完成bean的創(chuàng)建:

對(duì)應(yīng)的我們也給出AbstractAutowireCapableBeanFactory中instantiate實(shí)例化bean的實(shí)現(xiàn)印證這一說(shuō)法:

private Object instantiate(String beanName, RootBeanDefinition mbd,
   @Nullable Object factoryBean, Method factoryMethod, Object[] args) {

  try {
  
   else {
   //通過(guò)getInstantiationStrategy獲取上下文中對(duì)應(yīng)的創(chuàng)建策略完成bean的創(chuàng)建
    return this.beanFactory.getInstantiationStrategy().instantiate(
      mbd, beanName, this.beanFactory, factoryBean, factoryMethod, args);
   }
  }
  catch (Throwable ex) {
   //......
  }
 }


責(zé)任編輯:趙寧寧 來(lái)源: 寫(xiě)代碼的SharkChili
相關(guān)推薦

2025-05-09 09:05:00

Spring框架設(shè)計(jì)模式

2023-07-03 07:39:43

Spring框架設(shè)計(jì)模式

2010-06-11 14:55:20

2020-07-30 08:10:08

框架設(shè)計(jì)Spring Secu

2023-03-03 13:10:15

2020-09-04 14:10:31

架構(gòu)軟件互聯(lián)網(wǎng)

2009-06-24 17:21:23

JSF框架設(shè)計(jì)模式

2009-06-22 16:34:30

框架架構(gòu)設(shè)計(jì)模式

2009-06-22 16:24:33

JSF框架中使用的設(shè)計(jì)

2017-02-13 13:10:35

JavaScript設(shè)計(jì)模式

2011-04-22 09:26:57

MVC設(shè)計(jì)

2019-08-23 11:58:07

Java框架架構(gòu)

2011-07-08 14:01:26

Windows安全

2024-11-26 14:29:48

2022-09-21 09:01:27

Spring設(shè)計(jì)模式框架,

2024-06-19 16:02:46

2021-10-29 15:01:59

前端開(kāi)發(fā)技術(shù)

2009-07-30 14:03:04

ASP.NET中的se

2021-04-19 21:25:48

設(shè)計(jì)模式到元

2025-06-03 04:00:00

Spring框架配置
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 午夜免费影视 | 一区二区三区观看视频 | 亚洲成人中文字幕 | 日韩男人天堂 | 国产精品99精品久久免费 | 国产美女一区二区三区 | 黄色网址大全在线观看 | 91久久国产 | 国产成人精品一区二区三区视频 | 精品久久一区 | 日韩欧美网 | 亚洲国产精品激情在线观看 | 亚洲视频免费 | 国产精产国品一二三产区视频 | 国产精品一区久久久久 | 99国产精品久久久 | 亚洲性免费| 精品久久久久久久久久久久久久 | 91在线观看视频 | 国产精品一区二区在线 | 激情久久网 | 2018国产精品 | 日日操日日舔 | 亚洲免费视频在线观看 | 亚洲啊v| 日韩精品一区二 | 韩国电影久久 | 日本超碰 | 日韩在线视频一区二区三区 | 日韩在线视频网址 | 国产精品一区二区av | 久久久精彩视频 | 91精品国产一区二区三区 | 国产资源在线视频 | 99热精品在线观看 | 浮生影院免费观看中文版 | 国产亚洲成av人在线观看导航 | 国产激情在线 | 久久精品久久久 | 精品国产免费人成在线观看 | 国产高清视频在线 |